#include <stdio.h>
#include <stdlib.h> // exit
#include <unistd.h>
#include <iostream>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <iomanip>
#include <errno.h>
#include <sstream>      //std::ostringstream
#include<algorithm>
#include "cli.h"
#include "cliUtil.h"

using namespace cli;
using namespace std;

char sentMsgBuf[MAX_MSG_SIZE];
char recvMsgBuf[MAX_MSG_SIZE];
CliMessage sentMsg;
CliMessage recvMsg;

#define NEW_POWER       1
ModuleCollection * ModuleCollection::instance_m = NULL;
MessageHandler * MessageHandler::instance_m = NULL;

void Module::createCmd(U16 dst_id, U16 type, U16 code, string name, string tips)
{
    if(name.length()>=maxCmdWidth_m) maxCmdWidth_m = name.length() + 1;
    Command *cmd = new Command(dst_id, type, code, name, tips);
    cmdList_m.push_back(cmd);
}

Command * Module::extractCmd(string orgStr)
{
    orgStr.erase(0, orgStr.find_first_not_of(" "));
    string cmdStr;
    if(orgStr.find(' '))
    {
        cmdStr = orgStr.substr(0,orgStr.find(' '));
    }

    Command *cmd = NULL;
    for(unsigned i=0; i<cmdList_m.size(); i++)
    {
        Command *tmpCmd = cmdList_m[i];
        if(cmdStr.compare(tmpCmd->getName())==0)
        {
            cmd = tmpCmd;
            break;
        }
    }
    return cmd;
    
}

void Module::listCmds(void)
{
    for(U16 i=0; i<cmdList_m.size(); i++)
    {
        Command *cmd = cmdList_m[i];
        cout << left;
        cout << " " << setw(maxCmdWidth_m) << cmd->getName() << " : " << cmd->getTips()<< endl;
    }
}


bool Module::matchCmd(char *cmd)
{
    string cmdStr(cmd);
    if(extractCmd(cmdStr))
    {
        return true;
    }
    return false;
    
}

bool Module::frontMatchCmd(char *cmd)
{
    string cmdStr(cmd);
    cmdStr.erase(0, cmdStr.find_first_not_of(" "));
    if(cmdStr.find(' '))
    {
        cmdStr = cmdStr.substr(0,cmdStr.find(' '));
    }

    for(U16 i=0; i<cmdList_m.size(); i++)
    {
        Command *tmpCmd = cmdList_m[i];
        if(tmpCmd->getName().find(cmdStr)==0)
        {
            return true;
        }
    }
    return false;
}

U16 Module::compensateCmd(char *cmd)
{
    string cmdStr(cmd);
    U16 cmdNum = 0;
    U16 cmdIdx = 0;
    for(U16 i=0; i<cmdList_m.size(); i++)
    {
        Command *tmpCmd = cmdList_m[i];
        if(tmpCmd->getName().find(cmdStr)==0)
        {
            cmdIdx = i;
            cmdNum++;
        }
    }
    if(cmdNum==1)
    {
        string newStr = cmdList_m[cmdIdx]->getName();
        memcpy(cmd, newStr.c_str(), newStr.length());
        return newStr.length() - cmdStr.length();
    }
    return 0;
}

void Module::visit(void)
{
    cout << name_m << " is being operated. Supported command list:" << endl;
    listCmds();
    cout << name_m << "> " << flush;

    char ch;
    struct termios cur_term;
    int ret ;
    tcgetattr(STDIN_FILENO, &term_m);
    memcpy(&cur_term, &term_m, sizeof(cur_term));
    cur_term.c_lflag &= ~(ICANON);// Disable standard input mode
    cur_term.c_lflag &= ~(ECHO); // Do NOT show input
    cur_term.c_iflag |= INLCR; // Do NOT show input
    cur_term.c_cc[VMIN] = 1;
    cur_term.c_cc[VTIME] = 0;
    
    ret = tcsetattr(STDIN_FILENO, TCSANOW, &cur_term);
    if (ret < 0)
    {
        printf("Can't set\n");
        return;
    }
    fflush(stdout);

    char cmd[MAX_CMD_LENGTH] = {0};
    U16 cmdIdx = 0, compensateLen = 0, curIdx = 0;

    bool is27 = false, is27_91 = false, is27_91_51 = false, is27_79 = false;
    
    while(true)
    {
        read(STDIN_FILENO, &ch, 1);
        
        //printf("\n%d\n", ch);
        
        //cout << "ASCII:" << ch << "," << (U16)ch << endl;
        if(27==ch)
        {
            is27 = true;
            ch = 0;
        }
        else if(is27)
        {
            if(91==ch)
            {
                is27_91 = true;
                ch = 0;
            }
            else if(79==ch)
            {
                is27_79 = true;
                ch = 0;
            }
            is27 = false;
        }
        else if(is27_79)
        {
            if(72==ch && curIdx>0)
            {// Home, Move the cursor to head of line.
                do
                {
                    cout << "\033[1D";
                    curIdx--;
                }
                while(curIdx>0);
                cout << flush;
            }
            else if(70==ch && cmdIdx>curIdx)
            {// End
                do
                {
                    cout << "\033[1C";
                    curIdx++;
                }
                while(cmdIdx>curIdx);
                cout << flush;
            }
            is27_79 = false;
            ch = 0;
        }
        else if(is27_91)
        {
            if(51==ch)
            {
                is27_91_51 = true;
            }
            else if(65==ch && cmdHistory_m.size()>0)
            { // Up
                for(U16 i=0; i<curIdx; i++)
                {
                    cout << "\033[1D";
                }
                cout << "\033[K" << flush;
                if(0==cmdHistoryIdx_m)
                {
                    cmdHistoryIdx_m = cmdHistory_m.size();
                    cmdIdx = 0;
                    curIdx = 0;
                    memset(cmd, 0, MAX_CMD_LENGTH);
                }
                else
                {
                    cmdHistoryIdx_m--;
                    cout << *cmdHistory_m[cmdHistoryIdx_m] << flush;
                    cmdIdx = cmdHistory_m[cmdHistoryIdx_m]->length();
                    curIdx = cmdIdx;
                    memcpy(cmd, cmdHistory_m[cmdHistoryIdx_m]->c_str(), curIdx);
                    cmd[curIdx] = '\0';                    
                }
            }
            else if(66==ch && cmdHistory_m.size()>0)
            {// Down
                for(U16 i=0; i<curIdx; i++)
                {
                    cout << "\033[1D";
                }
                cout << "\033[K" << flush;
                if((cmdHistory_m.size()-1)==cmdHistoryIdx_m)
                {
                    cmdHistoryIdx_m = cmdHistory_m.size();
                    cmdIdx = 0;
                    curIdx = 0;
                    memset(cmd, 0, MAX_CMD_LENGTH);                    
                }
                else
                {
                    if(cmdHistory_m.size()==cmdHistoryIdx_m)
                    {
                        cmdHistoryIdx_m = 0;
                    }
                    else
                    {
                        cmdHistoryIdx_m++;
                    }
                    cout << *cmdHistory_m[cmdHistoryIdx_m] << flush;
                    cmdIdx = cmdHistory_m[cmdHistoryIdx_m]->length();
                    curIdx = cmdIdx;
                    memcpy(cmd, cmdHistory_m[cmdHistoryIdx_m]->c_str(), curIdx);
                    cmd[curIdx] = '\0';
                }
            }
            else if(67==ch && curIdx < cmdIdx)
            { // Right
                cout << "\033[1C" << flush;
                curIdx++;
            }
            else if(68==ch && curIdx > 0) // Left
            { // Left
                cout << "\033[1D" << flush;
                curIdx--;
            }
            is27_91 = false;
            ch = 0;
        }
        else if(is27_91_51)
        {
            if(126==ch)
            {// Delete
                if(cmdIdx==curIdx)
                {
                    // Delete nothing
                }
                else
                {
                    cout << "\033[K";
                    cmdIdx--;
                    for(U16 i=curIdx; i<=cmdIdx; i++)
                    {
                        cmd[i] = cmd[i+1];
                        cout << cmd[i];
                    }
                    for(U16 i=0; i<(cmdIdx-curIdx); i++) cout << "\033[1D";
                    cout << flush;
                }
                
            }
            is27_91_51 = false;
            ch = 0;
        }

        switch(ch)
        {
            case 10: // line change
            case 13: // enter
                if(cmdIdx==0)
                {
                    cout << endl;
                }
                else if(matchCmd(cmd))
                {
                    //cout << endl << "Handling command[" << cmd << "]" 
                    cout << endl;
                    handleCmd(cmd);
                }
                else
                {
                    cout << endl << "can NOT found command[" << cmd << "]" << endl;
                }
                cout << name_m << "> " << flush;

                // reset
                cmdHistory_m.push_back(new string(cmd));
                cmdHistoryIdx_m = cmdHistory_m.size();
                memset(cmd, 0, MAX_CMD_LENGTH);
                cmdIdx = 0;
                curIdx = 0;
                break;
            case 9: // tab
                compensateLen = compensateCmd(cmd);
                if(compensateLen)
                {
                    for(U16 i=0; i<(cmdIdx-curIdx); i++) cout << "\033[1C";
                    for(int i=0; i<compensateLen; i++)
                    {
                        cout << cmd[cmdIdx+i];
                    }
                    cout << flush;
                    cmdIdx += compensateLen;
                    curIdx = cmdIdx;
                }
                break;
            case 8: // back space
            case 127:
                //cout << "this is backspace" << endl;
                if(curIdx>0)
                {
                    cout << "\033[1D\033[K";
                    curIdx--;
                    cmdIdx--;
                    for(U16 i=curIdx; i<=cmdIdx; i++)
                    {
                        cmd[i] = cmd[i+1];
                        cout << cmd[i];
                    }
                    for(U16 i=0; i<(cmdIdx-curIdx); i++) cout << "\033[1D";
                    cout << flush;
                }
                break;
            default:
                if(ch>31 && ch<127)
                {
                    if(curIdx<cmdIdx)
                    {
                        cout << "\033[K" << ch;
                        for(U16 i=cmdIdx; i>curIdx; i--)
                        {
                            cmd[i] = cmd[i-1];
                        }
                        cmd[curIdx] = ch;
                        cmdIdx++;
                        curIdx++;
                        for(U16 i=curIdx; i<cmdIdx; i++) 
                        {
                            cout << cmd[i];
                        }
                        for(U16 i=curIdx; i<cmdIdx; i++) 
                        {
                            cout << "\033[1D";
                        }
                        cout << flush;
                    }
                    else
                    {
                        cmd[cmdIdx++] = ch;
                        cmd[cmdIdx] = '\0';
                        if(frontMatchCmd(cmd))
                        {
                            cout << ch; 
                            cout << flush; // force flush buffer
                            curIdx++;
                        }
                        else
                        {
                            cmd[--cmdIdx] = '\0';
                        }
                    }
                }
                break;
        }
    }
}

void Module::handleCmd(const char *cmd)
{
    U32 i = 0;
    string cmdStr(cmd);
    vector<string> cmdParams;
    vector<string> rawStrings;
    string delim = " ";
    split(cmdStr, delim, &rawStrings);
    for(i = 0; i < rawStrings.size(); i++)
    {
       if(rawStrings[i].compare("") == 0) 
       {
           continue;
       }
       else
       {
           cmdParams.push_back(rawStrings[i]);
       }
    }

    handleCmd(cmdParams);
}
void Module::handleCmd(vector<string> &cmdParams)
{
    bool rc = false;

    if(cmdParams.size()==0)
    {
        cout << "Please input command:" << endl;
        listCmds();
        return;
    }
    
    string out_r = "";
    Command *cmd = extractCmd(cmdParams[0]);
    
    if(cmd==NULL)
    {
        cout << "Can NOT find command["<< cmdParams[0] <<"] in module[" << name_m
            << "], only below commands are supported:" << endl;
        listCmds();
    }
    else if(cmdParams[0].compare("help")==0)
    {
        listCmds();
    }
    else if(cmdParams[0].compare("exit")==0)
    {
        tcsetattr(STDIN_FILENO, TCSANOW, &term_m);
        ModuleCollection::getInstance()->listModules();
    }
    else if(cmdParams[0].compare("")==0)
    {
        // Do nothing
    }
    else
    {

        //clear queue first for mismatch
        MessageHandler::getInstance()->cleanQueue();
        // Step1: Initialize Messaage Header and Command Header
        sentMsg.msgHeader_m.msgType = MSG_TYPE_COMMAND;
        sentMsg.msgHeader_m.srcID = MODULE_CLI;
        sentMsg.msgHeader_m.dstID = cmd->getDstID();
        sentMsg.msgHeader_m.mType = get_mtype(sentMsg.msgHeader_m.dstID);
        sentMsg.cmdHeader_m.cmdType = cmd->getType();
        sentMsg.cmdHeader_m.cmdCode = cmd->getCode();
        sentMsg.cmdHeader_m.cmdIndex = 0;
    
        // Step2: Build Command Payload
        //for(U16 i=0; i<cmdParams.size(); i++) cout << cmd->getCode() << ":" << cmdParams[i] << endl;
        if(!encode(cmd->getCode(), cmdParams, sentMsg.cmdPayload_m, sentMsg.cmdHeader_m.cmdLength))
        {
            return;
        }
        sentMsg.msgHeader_m.msgLength = sizeof(MSGHEADER) + sizeof(CMDHEADER) + sentMsg.cmdHeader_m.cmdLength;

        // Step3: Send message to destination and wait for response
        if( ! MessageHandler::getInstance()->sendMsg((char *)&sentMsg, 
            sentMsg.msgHeader_m.msgLength) )
        {
            cout << __func__ << ": Can NOT sent message to module: " << name_m << endl;
            return;
        }

#if 0
        printf("sending ....\n");
        for ( int i = 0; i < 64; i++)
        {
            if(i % 8 == 0 && i != 0) printf("\n");

            printf("%02x ", *((char *)&sentMsg + sizeof(long) + i));
        }
        printf("\n");
#endif           
        //for phone info, there is another thread to receiving the following message
        if (cmd->getCode() == CMD_CODE_PHONE_INFO_TRANSFER_START || 
            cmd->getCode() == CMD_GSM_GET_SNIFFER_RESULT)
        {
            return;
        }
        
        // Step4: Receive and display response from destination
        //if(!MessageHandler::getInstance()->recvMsg((char *)&recvMsg))
        if(!MessageHandler::getInstance()->recvMsgNoWait((char *)&recvMsg))
        {
            cout << "NO response received." << endl;
            return;
        }
    
        PCMDHEADER pCmd = (PCMDHEADER) ((char*)&recvMsg + sizeof(MSGHEADER));

#if 0
        printf("receiving ....\n");
        for ( int i = 0; i < 64; i++)
        {
            if(i % 8 == 0 && i != 0) printf("\n");

            printf("%02x ", *((char *)&recvMsg + sizeof(long) + i));
        }
        printf("\n");
#endif            
        rc = decode(pCmd, out_r);
        //cout << ((char *)&recvMsg + sizeof(long)+ sizeof(MSGHEADER)+ sizeof(CMDHEADER)) << endl;
        cout << out_r << endl << flush;

        //for doing comannd
        if ((cmd->getCode() == CMD_CODE_GET_SIM_STATE ||
             cmd->getCode() == CMD_CODE_SYS_REBOOT) && rc)
        {
            out_r.clear();
            // Step4: Receive and display response from destination
            // if(!MessageHandler::getInstance()->recvMsg((char *)&recvMsg))
            if(!MessageHandler::getInstance()->recvMsgNoWait((char *)&recvMsg))
            {
                cout << "NO reponse received." << endl;
                return;
            }

            pCmd = (PCMDHEADER) ((char*)&recvMsg + sizeof(MSGHEADER));
#if 0
        printf("receiving ....\n");
        for ( int i = 0; i < 64; i++)
        {
            if(i % 8 == 0 && i != 0) printf("\n");

            printf("%02x ", *((char *)&recvMsg + sizeof(long) + i));
        }
        printf("\n");
#endif              
            decode(pCmd, out_r);

            //cout << ((char *)&recvMsg + sizeof(long)+ sizeof(MSGHEADER)+ sizeof(CMDHEADER)) << endl;
            cout << out_r << endl << flush;               
        } 

        if ((cmd->getCode() == CMD_CODE_SYS_UPGRADE) &&(recvMsg.msgHeader_m.srcID != MODULE_INTF) && rc)
        {
            out_r.clear();

            while(1)
            {
                cout << "===" << flush;
                usleep(50000); 
                cout << "===" << flush;
                if(!MessageHandler::getInstance()->recvMsgNoWait((char *)&recvMsg))
                {
                    continue;
                }
                else
                {
                    cout << endl;

                    pCmd = (PCMDHEADER) ((char*)&recvMsg + sizeof(MSGHEADER));

                    decode(pCmd, out_r);
                    cout << out_r << endl << flush;

                    break;
                }
            }
        }
    }
}

/*
Function: paramPackParam
Parameters:
    PPARAM *ppParam: [IN,OUT] pointer to current parameter, move to next parameter after completed.
    U32 paraType, U32 paraLength : [IN] 
    U8** pParaValue [OUT]  the pointer to a pointer which represent the start address of parameter value .  
        Caller must fill actual parameter value outside this function.
        The benefit of this implementation(  no memcpy inside) is to avoid memcpy twice for long parameter. For Example:

        The normal steps to fill  parameter value  in the format of a big structure: 
         1) create a temporay structure , fill value one by one.  
         2) copy the structure to adderess of parameter value.

        New approach if using implementation in this function can be that:
         1)  After calling this function caller can get  address of parameter value  
         2)  caller can cast  structure on this address directly and fill value one by one. 
     
Return:
     total length of current parameter 

*/
U32 Module::paramPackParam(PPARAM *ppParam, U32 paraType, U32 paraLength, U8** pParaValue)
{
    PPARAM pParam = *ppParam;
    U32 len = roundup8(sizeof(PARAM) + paraLength);
    pParam->paraType = paraType;
    pParam->paraLength = paraLength;
    *pParaValue = pParam->paraValue;
    *ppParam = (PPARAM)((U8*)(*ppParam) + len);

    return len;
}

U32 Module::packMsg1Param(U32 paraType, U32 paraLength, U8 *paraValue, char *payLoad)
{
    U32 len = 0;

    U64 *msgbuff = (U64 *)payLoad;

    PPARAM pParam = (PPARAM)(msgbuff);
    U8 *pValue = NULL;

    len = paramPackParam(&pParam,paraType,paraLength,&pValue);
    memcpy(pValue, paraValue, paraLength);

    return len; 
}

U32 Module::packMsg2Param(
    U32 paraType1,
    U32 paraLength1,
    U8 *paraValue1,
    U32 paraType2,
    U32 paraLength2,
    U8 *paraValue2,
    char *payLoad
    )
{
    U32 len = 0;

    U64 *msgbuff = (U64 *)payLoad;

    PPARAM pParam = (PPARAM)(msgbuff);
    U8 *pValue = NULL;


    len += paramPackParam(&pParam,paraType1,paraLength1,&pValue);
    memcpy(pValue, paraValue1, paraLength1);

    len += paramPackParam(&pParam,paraType2,paraLength2,&pValue);
    memcpy(pValue, paraValue2, paraLength2);

    return len;
}

U32 Module::packMsg3Param(
    U32 paraType1,
    U32 paraLength1,
    U8 *paraValue1,
    U32 paraType2,
    U32 paraLength2,
    U8 *paraValue2,
    U32 paraType3,
    U32 paraLength3,
    U8 *paraValue3,
    char *payLoad
    )
{
    U32 len = 0;

    U64 *msgbuff = (U64 *)payLoad;
    PPARAM pParam = (PPARAM)msgbuff;
    U8 *pValue = NULL;

    len += paramPackParam(&pParam,paraType1,paraLength1,&pValue);
    memcpy(pValue, paraValue1, paraLength1);

    len += paramPackParam(&pParam,paraType2,paraLength2,&pValue);
    memcpy(pValue, paraValue2, paraLength2);

    len += paramPackParam(&pParam,paraType3,paraLength3,&pValue);
    memcpy(pValue, paraValue3, paraLength3);
    
    return len; 
}

bool Module::decodeGeneralCmdResponse(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_RESULT:
                 oss << matchStringValue(operationResult, *((U32 *)paraValue));
                 break;
            case PARA_TYPE_ERROR_CODE:
                 oss << ", failure cause: " << matchStringValue(errorInfo, *((U32 *)paraValue)) << endl; 
                 break;
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;
        }

    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

const char* Module::matchStringValue(const value_string *vs, const U32 val)
{
    U32 i = 0;
  
    if(vs) 
    {
        while (vs[i].strptr) 
        {
            if (vs[i].value == val) 
            {
               return(vs[i].strptr);
            }

            i++;
        }
    }
  
    return NULL;
}

void ModuleCollection::queryModuleState(void)
{
    string cmd("status");

    for(unsigned i=0; i<moduleList_m.size(); i++)
    {
        Module *module = moduleList_m[i];
        U16 moduleId = module->getModuleId();

        //char cmd[] = "status";
        switch(moduleId)
        {
            case MODULE_SYSTEM:
                cout << "Check System Info ....." << endl;
                cmd= "info";
                module->handleCmd(cmd.c_str());

                cout << "Check System Status ....." << endl;
                cmd= "status";
                break;
            case MODULE_SMS:
                //step 1. first to get sim card state
                cout << "Check SIM Card Status ......" << endl;
                cmd = "getsimstate";

                //step 2.
                module->handleCmd(cmd.c_str());

                cout << "Check SMS Module Status ......" << endl;
                cmd = "getsmsstate";
                break;
            case MODULE_GSM_CAP:
                cout << "Check GSM Module Status ......" << endl;
                cmd = "status";
                break;
            case MODULE_PA:
                cout << "Check PA 0 Status ......" << endl;
                cmd = "status 0";
                module->handleCmd(cmd.c_str());
                cout << "Check PA 1 Status ......" << endl;
                cmd = "status 1";
                module->handleCmd(cmd.c_str());
                cout << "PA Output Power:" << endl;
                cmd= "getpower 0";
                module->handleCmd(cmd.c_str());
                cout << "PA Temperature:" << endl;
                cmd= "gettemp 0";
                module->handleCmd(cmd.c_str());     
                cout << "PA ZSWR:" << endl;
                cmd= "getzswr 0";
                break;
            case MODULE_PM:
                cout << "Check Power Module Status ......" << endl;
                cmd = "status";
                break;
            case MODULE_GPS:
                cout << "Check GPS Module Status ......" << endl;
                cmd = "status";
                break;
            case MODULE_DATAPRO:
                cout << "Check Data Module Status ......" << endl;
                cmd = "status";
                break;
            case MODULE_WIFI:
                cout << "Check Wifi Module Status ......" << endl;
                cmd = "status";
                break;
            case MODULE_INTF:
                cout<< "Check Fep Module Status ......" <<endl;
                cmd = "status";
                break;
            case MODULE_CDMA_CAP:
                cout << "Check CDMA Module Status ......" << endl;
                cmd = "status";
                break;                
            case MODULE_WCDMA_CAP:
                cout << "Check WCDMA Module Status ......" << endl;
                cmd = "status";
                break;
            case MODULE_TDSCDMA_CAP:
                cout << "Check WCDMA Module Status ......" << endl;
                cmd = "status";
                break;                
            default:
                continue;
                break;
        }

        module->handleCmd(cmd.c_str());
        cout << endl;
    }
}

void ModuleCollection::listModules(void)
{
    cout << "Please select module to be operated:" << endl;

    for(unsigned i=0; i<moduleList_m.size(); i++)
    {
        Module *module = moduleList_m[i];
        cout << " " << setw(2) << std::right << (i+1) << ") " << module->getName() << endl;
    }

    cout << " " << (moduleList_m.size() + 1) << ") Query Modules State." << endl;

    while(true)
    {
        cout << "Select Module: ";
        string choice;
        getline(cin, choice);
        unsigned n = atoi(choice.c_str());

        if(choice=="exit")
        {
            cout << "Bye-bye" << endl;
            exit(EXIT_SUCCESS);
        }
        else if(n==(moduleList_m.size()+1))
        {
            // TODO: query all modules' states.
            queryModuleState();
        }
        else if(n>0 && n<=moduleList_m.size())
        {
            moduleList_m[n-1]->visit();
        }
        else
        {
            cout << "Illegal choice[" << choice << "], please re-select." << endl;
        }
        cout << endl;
    }
}

void ModuleCollection::processCmd(int argc,char **argv)
{
    string modStr(argv[1]);
    if(modStr.compare("query-module-state")==0)
    {
        queryModuleState();
        return;
    }
    unsigned i=0;
    for(; i<moduleList_m.size(); i++)
    {
        Module *module = moduleList_m[i];
        if(module->getName().compare(modStr)==0)
        {
            // Find module, and then build cmdStr
            vector<string> cmdParams;
            for(U16 j=2; j<argc; j++)
            {
                string param(argv[j]);
                cmdParams.push_back(param);
            }

            if(cmdParams.size()>0 && cmdParams[0].compare("exit")==0)
            {
                cmdParams[0] = "help";
            }

            module->handleCmd(cmdParams);
            break;
        }
    }
    if(i==moduleList_m.size())
    {
        cout << "Can NOT found module[" << modStr << "], below modules are supportted:" << endl;
        for(unsigned i=0; i<moduleList_m.size(); i++)
        {
            Module *module = moduleList_m[i];
            cout << " " << module->getName() << endl;
        }
        cout << " query-module-state" << endl;
    }
}

void MessageHandler::init(void)
{
    // TODO: what kind of key id should be?
    key_t key = ftok("/tmp", MSGQ_FTOK_ID);
    if (key == (key_t)-1) 
    {
        printf("ftok(%d) failed, %s\n", MSGQ_FTOK_ID, strerror(errno));
        exit(EXIT_FAILURE);
    }
    rxQueueId_m = msgget(key, IPC_CREAT);

    key = ftok("/tmp", MSGQ_FTOK_ID ^ 0xff);
    if (key == (key_t)-1) 
    {
        printf("ftok(%d) failed, %s\n", MSGQ_FTOK_ID ^ 0xff, strerror(errno));
        if(txQueueId_m != 0)
        {   
            msgctl(txQueueId_m, IPC_RMID, NULL);
            txQueueId_m = 0;   
        }
        exit(EXIT_FAILURE);
    }
    txQueueId_m = msgget(key, IPC_CREAT);
}

bool MessageHandler::sendMsg(char *msg, U16 length)
{
    int ret_value = msgsnd(txQueueId_m, msg, length, 0);  
    if( ret_value < 0 ) {  
        printf("msgsnd() msg failed length=%d, errno=%d[%s]\n", length, errno, strerror(errno));  
        return false;  
    }
    return true;
}

bool MessageHandler::recvMsg(char *msg)
{
    if(msgrcv(rxQueueId_m, (void*)msg, MAX_MSG_SIZE, MSGQ_TYPE_CLI, 0)<0)
    {
        int err = errno;
        if(err <= 0 && err != EINTR)
        {
            printf("Error %s\n",strerror(err));
        }
        return false;
    }
    return true;
}

bool MessageHandler::recvMsgNoWait(char *msg)
{
    int  i = 0;

    while(1)
    {
        if(msgrcv(rxQueueId_m, (void*)msg, MAX_MSG_SIZE, MSGQ_TYPE_CLI, IPC_NOWAIT) < 0)
        {
            int err = errno;
            if(err <= 0 && err != ENOMSG)
            {
                printf("Error %s\n",strerror(err));
                return false;
            }

            usleep(100000);
            i++;
        }
        else
        {
            return true;
        }

        if(i >= 10000)
        {
            return false;
        }
    }

    return true;
}

bool MessageHandler::cleanQueue()
{
    char msg[MAX_MSG_SIZE] = {0};

    while(1)
    {
        if(msgrcv(rxQueueId_m, (void*)msg, MAX_MSG_SIZE, MSGQ_TYPE_CLI, IPC_NOWAIT) < 0)
        {
            int err = errno;
            if(err <= 0 && err != ENOMSG)
            {
                printf("Error %s\n",strerror(err));
                return false;
            }
            else if(err == ENOMSG)
            {
                //there is no any message more, just break;
                break;
            }
        }
    }

    return true;
}

int main(int argc, char **argv)
{
    // Initialize message handler
    MessageHandler::getInstance()->init();

    //because the message queue is system resource,
    //it need be cleaned to avoid to recevied the stale message
    MessageHandler::getInstance()->cleanQueue();

    // Initialize modules and commands if need
    ModuleCollection *col = ModuleCollection::getInstance();
    col->addModule(new ModuleSystem());
    col->addModule(new ModuleData());    
    col->addModule(new ModulePower());
    col->addModule(new ModulePa());	
    col->addModule(new ModuleFep());
    col->addModule(new ModuleMessage);
    col->addModule(new ModuleGsm());
    col->addModule(new ModuleCdma());	
    col->addModule(new ModuleWifi());
    col->addModule(new ModuleEutran());
    col->addModule(new ModuleWcdma());
    col->addModule(new ModuleTdscdma());
    col->addModule(new ModuleScanner());
    col->addModule(new ModuleFwmgr());	
    col->addModule(new Module3G());
    col->addModule(new ModuleGps());

    if(argc>1)
    {
        col->processCmd(argc, argv);
    }
    else
    {
        col->listModules();
    }

    exit(EXIT_SUCCESS);
}

Module3G::Module3G():Module(MODULE_SMS, "3G")
{
    createCmd(MODULE_SMS, CMD_SET, CMD_CODE_SMS_OFF, "smsoff", "close sms function.");
    createCmd(MODULE_SMS, CMD_SET, CMD_CODE_SMS_ON, "smson", "open sms function.");
    createCmd(MODULE_SMS, CMD_SET, CMD_CODE_SMS_REPORT, "smsreport", "report sms message.");
    createCmd(MODULE_SMS, CMD_SET, CMD_CODE_SEND_SMS, "sendsms", "Usage: sendsms <called number> <ascii | unicode> <message>.");
    createCmd(MODULE_SMS, CMD_SET, CMD_CODE_SYSMONITOR_TEST_MODULE, "TestModuleSMS", "usage: 0 is 3gdongle | 1 is smstask | 2 is checkWan");
    createCmd(MODULE_SMS, CMD_GET, CMD_CODE_GET_SIM_STATE, "getsimstate", "get sim state.");
    createCmd(MODULE_SMS, CMD_GET, CMD_CODE_GET_SMS_STATE, "getsmsstate", "get sms state.");
}

bool Module3G::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool rc = false;
    len = 0;
    switch(cmdCode)
    {
        case CMD_CODE_SMS_OFF:
            rc = true;
            break;
        case CMD_CODE_SMS_ON:
            rc = true;
            break;
        case CMD_CODE_GET_SIM_STATE:
            rc = true;
            break;
        case CMD_CODE_GET_SMS_STATE:
            rc = true;
            break;
        case CMD_CODE_SYSMONITOR_TEST_MODULE:
            rc = sendModuleTest(params, payload, len);
            break;
        case CMD_CODE_SMS_REPORT:
            rc = buildSmsReport(params, payload, len);
            break;
        case CMD_CODE_SEND_SMS:
            rc = buildSendSms(params, payload, len);
            break; 
        default:
            cout << "Unknown cmdCode: " << cmdCode << endl; 
            break;
    }

    return rc;
}

bool Module3G::sendModuleTest(vector<string>& params, char* payload, U16& len)
{
    if ( params.size() != 2)
    {
        cout << "Invalid command" << std::endl;
        return false;
    }
    U32 thread = 0;
    if ( atoi(params[1].c_str()) == PARA_VALUE_SYSMONITOR_MAIN )
    {        
        thread = PARA_VALUE_SYSMONITOR_MAIN;
    }
    else if ( atoi(params[1].c_str()) == PARA_VALUE_SYSMONITOR_THREAD1 )
    {
        thread = PARA_VALUE_SYSMONITOR_THREAD1;
    }
    else
    {
        thread = PARA_VALUE_SYSMONITOR_THREAD2;
    }
    len = packMsg1Param( PARA_TYPE_SYSMONITOR_TEST, 4, (U8 *)&thread,
                        payload);
    return true;

}

bool Module3G::buildSmsReport(vector<string> &params, char *payload, U16 &len)
{
    return true;
}

bool Module3G::buildSendSms(vector<string> &params, char *payload, U16 &len)
{
    U32 codeType; 
    U32 textNum = 0;
    string message;
    string blank(" ");

    if (params.size() < 4)
    {
        cout << "Parameter number should be larger than 4" << endl;
        return false;
    }

    if (params[2].compare("ascii") == 0)
    {
        codeType = PARA_VALUE_3G_SMS_FORMAT_ASCII;
    }
    else if (params[2].compare("unicode") == 0)
    {
        codeType = PARA_VALUE_3G_SMS_FORMAT_UNICODE;
    }
    else
    {
        cout << "SMS format shoulde be ascii or unicode" << endl;
        return false;
    }

    if (codeType == PARA_VALUE_3G_SMS_FORMAT_UNICODE)
    {
        char out1[MAX_CMD_LENGTH];
        string val;

        if(getCnString(params[3], val))
        {
             //cout << "found UTF-8 string:" << "[" << val.c_str() << "]" << endl; 

             // UNICODE-->utf-8
             CodeConverter cc4 = CodeConverter("utf-8","UNICODEBIG");
             cc4.convert(val.c_str(), val.length(), out1, MAX_CMD_LENGTH);

             for(unsigned i=0; i<strlen(out1); i++)
             {
                 printf("0x%hhx", out1[i]);
                 if(i!=(strlen(out1)-1)) cout << ",";
             }             

             //cout << "UNICODE-->utf-8 in=[" << val.c_str() << "], out=[" << out1 << "]" << endl;             
             len = packMsg3Param(PARA_TYPE_3G_SMS_CALLED_ID, params[1].length(), (U8 *)params[1].c_str() , 
                                 PARA_TYPE_3G_SMS_FORMAT, 4, (U8 *)&codeType, 
                                 PARA_TYPE_3G_SMS_TEXT, strlen(out1), (U8 *)out1, payload);

             return true;
        }
        else
        {
            cout << "NO such chinese words" << endl;
            return false;
        }
    }

    for (textNum = 3; textNum < params.size(); textNum++)
    {
       message += params[textNum] + blank;
    }

    cout << message << endl;

    len = packMsg3Param(PARA_TYPE_3G_SMS_CALLED_ID, params[1].length(), (U8 *)params[1].c_str() , 
                        PARA_TYPE_3G_SMS_FORMAT, 4, (U8 *)&codeType, 
                        PARA_TYPE_3G_SMS_TEXT, message.length(), (U8 *)message.c_str(), payload);

    return true;
}

bool Module3G::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    bool rc = false;
    if (pCmd->cmdType == CMD_GENERAL_RESPONSE)
    {
        oss << "Error command, cmdCode " << hex << pCmd->cmdCode << endl;
        out_r += oss.str();
        return rc;
    }

    switch(pCmd->cmdCode)
    {
        case CMD_CODE_SMS_OFF:
        case CMD_CODE_SMS_ON:
        case CMD_CODE_SMS_REPORT:
        case CMD_CODE_SEND_SMS:
            rc = decodeGeneralCmdResponse(pCmd, out_r);
            break;
        case CMD_CODE_GET_SIM_STATE:
        case CMD_CODE_GET_SMS_STATE:
            rc = decodeGetSimAndSmsState(pCmd, out_r);
            break;
        default:
            oss << "Unknown cmdCode:" << pCmd->cmdCode << endl;            
            break;
    }

    out_r += oss.str();

    return rc;
}

bool Module3G::decodeGetSimAndSmsState(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;

    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_3G_SIM_STATE:
                oss << "SIM State: " << matchStringValue(simState, *((U32*)paraValue)) << endl;
                break;
            case PARA_TYPE_3G_SMS_STATE:
                oss << "SMS State: " << matchStringValue(smsState, *((U32*)paraValue)) << endl;
                break;
            case PARA_TYPE_RESULT:
                oss << matchStringValue(operationResult, *((U32 *)paraValue)) << endl;                
                break;
            default:
                oss << __func__ << "  Unknown result type: " << paraType << endl;                
                break;
        }

    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();

    return true;
}


ModuleGsm::ModuleGsm():Module(MODULE_GSM_CAP, "gsm")
{
    createCmd(MODULE_GSM_CAP, CMD_SET, CMD_GSM_RESET,           "reset", "Reset gsm module.");    
    createCmd(MODULE_GSM_CAP, CMD_SET, CMD_GSM_WIRELESS_OFF,      "stop", "Usage: stop [<carrierIdx [0|1]>].");    
    createCmd(MODULE_GSM_CAP, CMD_SET, CMD_GSM_WIRELESS_ON,       "start", "Usage: start [<carrierIdx [0|1]>].");    
    createCmd(MODULE_GSM_CAP, CMD_SET, CMD_GSM_AIR_SNIFFER_OFF,   "snifferoff", "Usage: snifferoff.");    
    createCmd(MODULE_GSM_CAP, CMD_SET, CMD_GSM_AIR_SNIFFER_ON,    "snifferon", "Usage: snifferon.");    
    createCmd(MODULE_GSM_CAP, CMD_SET, CMD_GSM_DO_SNIFFER,    "dosniffer", "Request gsm module to sniffer.");    
    createCmd(MODULE_GSM_CAP, CMD_GET, CMD_GSM_GET_MODULE_STATUS, "status", "Get gsm module status.");
    createCmd(MODULE_GSM_CAP, CMD_GET, CMD_GSM_GET_MODULE_CFG,    "displaycfg", "Usage: displaycfg <carrierIdx [0|1]>.");
    createCmd(MODULE_GSM_CAP, CMD_SET, CMD_GSM_CFG_WIRELESS,      "cfggsm", "Usage: cfggsm <frequency> <mcc> <mnc> <lac> <band> <carrier> <cro> <minrssi> <threshold> <captime> <dnatt> <upatt> <cnum> <configMode> <workMode> <startFreq900> <endFreq900> <startFreq1800> <endFreq1800> <freqOffset> ."); 
    createCmd(MODULE_GSM_CAP, CMD_SET, CMD_GSM_CFG_AIR_SNIFFER,   "cfgsniffer", "Usage: cfgsniffer <bccautoMode[1~5]> <isauto> <hour> <minute> <second> <cycle> .");    
    createCmd(MODULE_GSM_CAP, CMD_SET, CMD_GSM_CFG_RECURING_INTERVAL, "cfginterval", "Usage: cfginterval <minutes>.");    
    createCmd(MODULE_GSM_CAP, CMD_GET, CMD_GSM_GET_SNIFFER_RESULT,  "snifresult", "get sniffer result.");
    createCmd(MODULE_GSM_CAP, CMD_GET, CMD_GSM_GET_SEND_COUNTER,  "getcounter", "get internal sending counter.");
    createCmd(MODULE_GSM_CAP, CMD_GET, CMD_GSM_GET_SNIFFER_CFG,  "dispsnifcfg", "display sniffer configuration.");
    createCmd(MODULE_GSM_CAP, CMD_SET, CMD_GSM_TX_ATTUATION,  "settxatt", "Usage: settxatt <attuation (0~90 dB)>.");
    createCmd(MODULE_GSM_CAP, CMD_SET, CMD_GSM_UPGRADE,  "upgrade", "Usage: upgrade");
    createCmd(MODULE_GSM_CAP, CMD_GET, CMD_GSM_GET_VERSION,  "getVersion", "usage: getVersion");
    createCmd(MODULE_GSM_CAP, CMD_GET, CMD_GSM_GET_CHOICE_ARFCN,  "getChoiceArfcn", "usage: getChoiceArfcn");
    createCmd(MODULE_GSM_CAP, CMD_SET, CMD_GSM_RESTART,  "restart", "usage: restart");
}

bool ModuleGsm::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool result = false;

    len = 0;
    switch(cmdCode)
    {
        case CMD_GSM_RESET:
        case CMD_GSM_WIRELESS_OFF:
        case CMD_GSM_WIRELESS_ON:
        case CMD_GSM_AIR_SNIFFER_OFF:
        case CMD_GSM_AIR_SNIFFER_ON:
        case CMD_GSM_DO_SNIFFER:
        case CMD_GSM_UPGRADE:
        case CMD_GSM_GET_VERSION:
        case CMD_GSM_RESTART:
        case CMD_GSM_GET_CHOICE_ARFCN:
            result = buildSetCmdMsg(params, payload, len);
            break;
        case CMD_GSM_GET_MODULE_STATUS:
            result = true;
            break;
        case CMD_GSM_GET_SEND_COUNTER:
            result = true;
            break;
        case CMD_GSM_CFG_RECURING_INTERVAL:
            result = buildCfgRecuringInterval(params, payload, len);
            break;
        case CMD_GSM_GET_MODULE_CFG:
            result = buildGetModuleCfg(params, payload, len);
            break;

        case CMD_GSM_CFG_WIRELESS:
            result = buildCfgGsmCapModule(params, payload, len);
            break;

        case CMD_GSM_CFG_AIR_SNIFFER:
            result = buildCfgGsmSnifferModule(params, payload, len);
            break;
        case CMD_GSM_GET_SNIFFER_RESULT:
            if(createRcvSnifferResultThread())
            {
                statNumber = 0;
                stat.clear();

			    result = true;
            }
			else
			{
			    result = false;
			}
            break;
        case CMD_GSM_GET_SNIFFER_CFG:
            result = true;
            break;
        case CMD_GSM_TX_ATTUATION:
            result = buildSetGsmTxAttuation(params, payload, len);
            break;

                

        default:
            cout << __func__ << "  Unknown cmdCode: " << cmdCode << endl;              
            break;
    }

    return result;
}

bool ModuleGsm::buildSetGsmTxAttuation(vector<string> &params, char *payload, U16 &len)
{
    int attuation = 0;

    if (params.size() < 2)
    {
        cout << "Parameter number should be 2" << endl;
        return false;
    }

    attuation = atoi(params[1].c_str());

    if(attuation > 90 || attuation <= 0)
    {
        cout << "attuation should be larger than 0, and smaller or equal than 90" << endl;
        return false;
    }

    len = packMsg1Param(PARA_TYPE_TX_ATTUATION, 4,  (U8 *)&attuation , payload);

    return true;
}

bool ModuleGsm::buildCfgRecuringInterval(vector<string> &params, char *payload, U16 &len)
{
    U32 minutes = 10;

    if (params.size() < 2)
    {
        cout << "Parameter number should be 2" << endl;
        return false;
    }

    minutes = atoi(params[1].c_str());

    len = packMsg1Param(PARA_TYPE_RECURING_INTERVAL, 4,  (U8 *)&minutes , payload);

    return true;
}

bool ModuleGsm::buildSetCmdMsg(vector<string> &params, char *payload, U16 &len)
{
    U32 carrier = 0;

    if (params.size() == 1)
        return true;

    if (params[1].compare("0") == 0)
    {
        carrier = PARA_VALUE_GSM_CARRIER_1;
    }
    else if (params[1].compare("1") == 0)
    {
        carrier = PARA_VALUE_GSM_CARRIER_2;
    }
    else 
    {
        cout << "Carrier index should be 0 or 1" << endl;
        return false;
    }

    len = packMsg1Param(PARA_TYPE_GSM_CARRIER_INDEX, 4,  (U8 *)&carrier , payload);

    return true;
}

bool ModuleGsm::buildCfgGsmSnifferModule(vector<string> &params, char *payload, U16 &len)
{
    U32 i = 1;
    snifferParam_t snParam;
    if (params.size() < 7)
    {
        cout << "parameters number should be 7" << endl;
        cout << "Usage: cfgsniffer <bccautoMode[1~5]> <isauto> <hour> <minute> <second> <cycle> ." << endl;
        return false;
    }

    snParam.autoBccMode = (U8)atoi(params[i++].c_str());
    snParam.isAuto = (U8)atoi(params[i++].c_str());
    snParam.hour = (U8)atoi(params[i++].c_str());   
    snParam.minutes = (U8)atoi(params[i++].c_str());
    snParam.second =  (U8)atoi(params[i++].c_str());
    snParam.snifferInterval = (U8)atoi(params[i++].c_str());

    cout << "Sniffer strategy:" << endl; 
    cout << "    bccAutoMode: " << (int)snParam.autoBccMode << endl;
    cout << "    isAuto: " << (int)snParam.isAuto << endl;
    cout << "    hour: " << (int)snParam.hour<< endl;
    cout << "    minute: " << (int)snParam.minutes << endl;
    cout << "    second: " << (int)snParam.second << endl;
    cout << "    cycle: " << (int)snParam.snifferInterval << endl;

    len = packMsg1Param(PARA_TYPE_GSM_SNIFFER_CONFIGURATION, sizeof(snifferParam_t),  (U8 *)&snParam , payload);

    return true;
}

bool ModuleGsm::buildCfgGsmCapModule(vector<string> &params, char *payload, U16 &len)
{
    U32 i = 1;
    geranParam_t geranP;
    if (params.size() < 10 )
    {
        cout << "parameters number should be 10" << endl;
        cout << "Usage: cfggsm <frequency> <mcc> <mnc> <lac> <band> <carrier> <cro> <minrssi> <threshold> <captime> <dnatt> <upatt> <cnum> <configMode> <workMode> <startFreq900> <endFreq900> <startFreq1800> <endFreq1800> <freqOffset>" << endl;
        return false;
    }

    geranP.frequency = atoi(params[i++].c_str());
    geranP.mcc = atoi(params[i++].c_str());
    geranP.mnc = atoi(params[i++].c_str());
    geranP.lac =  atoi(params[i++].c_str());
    geranP.band = atoi(params[i++].c_str());
    geranP.carrier = atoi(params[i++].c_str());
    geranP.cro = atoi(params[i++].c_str());
    geranP.rssiMin = atoi(params[i++].c_str());
    geranP.thresholdDelta = atoi(params[i++].c_str()); 
    geranP.captime  = atoi(params[i++].c_str()); 
    geranP.dnatt = atoi(params[i++].c_str()); 
    geranP.upatt = atoi(params[i++].c_str()); 
    geranP.cnum = atoi(params[i++].c_str()); 
    geranP.configMode = atoi(params[i++].c_str()); 
    geranP.workMode  = atoi(params[i++].c_str()); 
    geranP.startFreq900 = atoi(params[i++].c_str()); 
    geranP.endFreq900 = atoi(params[i++].c_str()); 
    geranP.startFreq1800 = atoi(params[i++].c_str()); 
    geranP.endFreq1800 = atoi(params[i++].c_str()); 
    geranP.freqOffset = atoi(params[i++].c_str()); 

    

    cout << "Carrier "<< geranP.carrier << " configuration:" << endl; 
    cout << "    Frequency: " << geranP.frequency << endl;
    cout << "    MCC: " << geranP.mcc << endl;
    cout << "    MNC: " << geranP.mnc << endl;
    cout << "    LAC: " << geranP.lac << endl;
    cout << "    Band: " << geranP.band << endl;    
    cout << "    Carrier: " << geranP.carrier << endl;
    cout << "    cro: " << geranP.cro << endl;
    cout << "    RssiMin: " << geranP.rssiMin << endl;
    cout << "    ThresholdDelta: " << geranP.thresholdDelta << endl;
    cout << "    Captime: " << geranP.captime << endl;
    cout << "    Dnatt: " << geranP.dnatt << endl;
    cout << "    Upatt: " << geranP.upatt << endl;
    cout << "    Cnum: " << geranP.cnum << endl;
    cout << "    ConfigMode: " << geranP.configMode << endl;
    cout << "    WorkMode: " << geranP.workMode << endl;
    cout << "    startFreq900: " << geranP.startFreq900 << endl;
    cout << "    endFreq900: " << geranP.endFreq900 << endl;
    cout << "    startFreq1800: " << geranP.startFreq1800 << endl;
    cout << "    endFreq1800: " << geranP.endFreq1800 << endl;
    cout << "    freqOffset: " << geranP.freqOffset << endl;



    len = packMsg1Param(PARA_TYPE_GSM_WIRELESS_CONFIGURATION, sizeof(geranParam_t),  (U8 *)&geranP , payload);

    return true;
}

bool ModuleGsm::buildGetModuleCfg(vector<string> &params, char *payload, U16 &len)
{
    //the second param is carrier
    U32 carrier = atoi(params[1].c_str());
    if (carrier != PARA_VALUE_GSM_CARRIER_1 && 
        carrier != PARA_VALUE_GSM_CARRIER_2)
    {
        printf("wrong carrier = %d, it should be 0 or 1 \n", carrier);
        return false;
    }

    len = packMsg1Param(PARA_TYPE_GSM_CARRIER_INDEX, 4,  (U8 *)&carrier , payload);

    return true;
}

bool ModuleGsm::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;

    bool rc = false;

    switch(pCmd->cmdCode)
    {
        case CMD_GSM_RESET:
        case CMD_GSM_WIRELESS_OFF:
        case CMD_GSM_WIRELESS_ON:
        case CMD_GSM_AIR_SNIFFER_OFF:
        case CMD_GSM_AIR_SNIFFER_ON:
        case CMD_GSM_DO_SNIFFER:
        case CMD_GSM_CFG_WIRELESS:    
        case CMD_GSM_CFG_AIR_SNIFFER:
        case CMD_GSM_TX_ATTUATION:
        case CMD_GSM_UPGRADE:
        case CMD_GSM_RESTART:
            rc = decodeGeneralCmdResponse(pCmd, out_r);
            break;            

        case CMD_GSM_GET_MODULE_STATUS:
            rc = decodeGetGsmMOduleStatus(pCmd, out_r);
            break;

        case CMD_GSM_GET_MODULE_CFG:            
            rc = decodeGetGsmModuleConfiguration(pCmd, out_r);
            break;

        case CMD_GSM_GET_SEND_COUNTER:
            rc = decodeGetGsmSendingCounter(pCmd, out_r);
            break;
        case CMD_GSM_GET_SNIFFER_RESULT:
            rc = decodeGetSnifferResult(pCmd, out_r);
            break;
        case CMD_GSM_GET_SNIFFER_CFG:
            rc = decodeGetSnifferConfiguration(pCmd, out_r);
            break;

        case CMD_GSM_GET_VERSION:
            rc = decodeGetVerison(pCmd, out_r);
            break;
        
        case CMD_GSM_GET_CHOICE_ARFCN:
            rc = decodeGetGsmChoiceArfcn(pCmd, out_r);
            break;

        default:
            oss << __func__ << " Unknown cmdCode:" << pCmd->cmdCode << endl;
            break;
    } 

    out_r += oss.str();
    return rc;
}


bool ModuleGsm::decodeGetGsmChoiceArfcn(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_SNIFFER_RESULT:
                oss << "GSM choice arfcn" <<endl;
                oss << paraValue << endl;
                break;
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;                 
        }

    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;


}

bool ModuleGsm::decodeGetVerison(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_GSM_VERSION:
                 oss << "GSM Module version: " << paraValue << endl;
                 break;
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;                 
        }

    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}


bool ModuleGsm::decodeGetSnifferConfiguration(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    snifferParam_t * snifferP;
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_GSM_SNIFFER_CONFIGURATION:
                snifferP = (snifferParam_t *) paraValue;
                oss << "Sniffer configuration:" << endl; 
                oss << "    autoBccMode: " << (int)snifferP->autoBccMode << endl;
                oss << "    isAuto: " << (int)snifferP->isAuto << endl;
                oss << "    hour: " << (int)snifferP->hour << endl;
                oss << "    minutes: " << (int)snifferP->minutes << endl;
                oss << "    second: " << (int)snifferP->second << endl;
                oss << "    snifferInterval: " << (int)snifferP->snifferInterval << endl;
                break;
            case PARA_TYPE_RESULT:
                oss << matchStringValue(operationResult, *((U32 *)paraValue)) << endl;
                break;
            case PARA_TYPE_ERROR_CODE:
                 oss << ", failure cause: " << matchStringValue(errorInfo, *((U32 *)paraValue)) << endl; 
                 break;                
            default:
                oss << __func__ << "  Unknown result type: " << paraType << endl;
                break;
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "  Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();    
    return true;
}


bool ModuleGsm::decodeGetGsmModuleConfiguration(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    geranParam_t * geranP;
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_GSM_WIRELESS_CONFIGURATION:
                geranP = (geranParam_t *) paraValue;
                oss << "Carrier " << geranP->carrier <<" configuration:" << endl; 
                oss << "    frequency: " << geranP->frequency << endl;
                oss << "    mcc: " << geranP->mcc << endl;
                oss << "    mnc: " << geranP->mnc << endl;
                oss << "    lac: " << geranP->lac << endl;
                oss << "    band: " << geranP->band << endl;
                oss << "    carrier: " << geranP->carrier << endl;
                oss << "    cro: " << geranP->cro << endl;
                oss << "    rssiMin: " << geranP->rssiMin << endl;
                oss << "    thresholdDelta: " << geranP->thresholdDelta << endl;
                oss << "    Captime: " << geranP->captime << endl;
                oss << "    Dnatt: " << geranP->dnatt << endl;
                oss << "    Upatt: " << geranP->upatt << endl;
                oss << "    Cnum: " << geranP->cnum << endl;
                oss << "    ConfigMode: " << geranP->configMode << endl;
                oss << "    workMode: " << geranP->workMode << endl;
                oss << "    startFreq900: " << geranP->startFreq900 << endl;
                oss << "    endFreq900: " << geranP->endFreq900 << endl;
                oss << "    startFreq1800: " << geranP->startFreq1800 << endl;
                oss << "    endFreq1800: " << geranP->endFreq1800 << endl;
                oss << "    freqOffset: " << geranP->freqOffset << endl;


                break;
            case PARA_TYPE_RESULT:
                oss << matchStringValue(operationResult, *((U32 *)paraValue)) << endl;
                break;
            case PARA_TYPE_ERROR_CODE:
                 oss << ", failure cause: " << matchStringValue(errorInfo, *((U32 *)paraValue)) << endl; 
                 break;                
            default:
                oss << __func__ << "  Unknown result type: " << paraType << endl;
                break;
        }


    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "  Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();    
    return true;
}

bool ModuleGsm::decodeGetGsmMOduleStatus(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_GSM_MODULE_STATUS:
                 oss << "GSM Module State: " << paraValue << endl;
                 break;
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;                 
        }

    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

bool ModuleGsm::decodeGetGsmSendingCounter(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    U32 *value;
    U32 i = 0;
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_GSM_SEND_COUNTER:
                 value = (U32 *)paraValue;
                 oss << "RC_OK: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_FAIL: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_OUT_OF_MEMORY: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_NULL_RESULT: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_MSG_TOO_LONG: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_MSG_NO_BUFF: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_MSG_DST_INVALID: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_MSG_QUEUE_FULL: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_MSG_CORRUPTED: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_MSG_INVALID_VALUE: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_UDP_COUNTER: " << setw(20) << *(value + (i++)) << endl;
                 break;
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;                 
        }

    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}


bool ModuleGsm::decodeGetSnifferResult(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    rawSnifferResult *pSnf = NULL;
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_SNIFFER_RESULT:
                 if(paraLength > 0)
                 {
                     
                     pSnf = (rawSnifferResult *)paraValue;
                     

                     char plmn[6] = {0};
                     for(int i = 0; i < 5; i++)
                     {
                         plmn[i] = 3 << 4 | pSnf->bPLMNId[i];
                     }

					 oss << "cell info: "<< endl;
                     
					 oss << "cellId: " << setw(8) << pSnf->bGlobalCellId << "  PLMN: " << setw(8) << plmn;
                     oss << "  RSSI: " << setw(8) << (S16)pSnf->cRSSI << "  LAC: " << setw(8) << pSnf->wLAC << "  BSIC: " << setw(8) << pSnf->wBSIC;
                     oss << "  ARFCN: " << setw(8) << pSnf->wARFCN << "  C1: " << (S16)pSnf->cC1 << "  C2: " << (U16)pSnf->bC2 << endl;
					 oss << "neighbor cell info, " << "number cell: " << (U16)pSnf->bNbCellNum << endl;
                     
                     for(int i = 0; i < pSnf->bNbCellNum; i++)
                     {
                         bool isFound = false;

                         //if(pSnf->stNbCell[i].bC2 == 0 && pSnf->stNbCell[i].cC1 == 0) continue;
                         for(vector<statArfcn>::iterator it=stat.begin(); it != stat.end(); it++)
                         {
                             if(pSnf->stNbCell[i].wARFCN == it->wARFCN) 
                             {
                                 isFound = true;
                                 it->count++;
                             }
                         }

                         if(!isFound)
                         {
                             statArfcn tmparfcn;
                             tmparfcn.wARFCN = pSnf->stNbCell[i].wARFCN;
                             tmparfcn.cRSSI = pSnf->stNbCell[i].cRSSI;
                             tmparfcn.count = 1;;
                             stat.push_back(tmparfcn);
                         }

						 oss << "BSIC: " << setw(8) << pSnf->stNbCell[i].wBSIC << "  ARFCN: " << setw(8) << pSnf->stNbCell[i].wARFCN;
                         oss << "  RSSI: " << setw(8) << (S16)pSnf->stNbCell[i].cRSSI << "  C1: " << setw(8) << (S16)pSnf->stNbCell[i].cC1; 
                         oss << "  C2: " << setw(8) << (U16)pSnf->stNbCell[i].bC2;
						 oss << endl;
                     }
                     

                 }
				 else
				 {
                     
                     if(statNumber > 0) oss << "ID " << setw(10) << "ARFCN " << setw(10) << "RSSI " << setw(10) << "occurrences " << endl;
                     
                     sort(stat.begin(), stat.end(), greater<statArfcn>());
                     int j = 0;
                     for(vector<statArfcn>::iterator it=stat.begin(); it != stat.end(); it++)
                     {
                         oss  << j++ << setw(10) << it->wARFCN <<  setw(10) << (S16)it->cRSSI << setw(10) <<  it->count << endl;
                     }
                    
				     oss << "No More Info." << endl;
					 hasMore = false;
				 }
				 
                 break;
            case PARA_TYPE_SNIFFER_BUSY:
                 oss << "Sniffer is on going, wait a minutes" << endl;
                 break;
            case PARA_TYPE_NO_NEIGHBOR_CELL:
                 oss << "No neighboring cell " << endl;
                 break;
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;                 
        }

    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

void ModuleGsm::handleSnifferResultMessage()
{
    hasMore = true;
    recordNum = 0;
    ostringstream oss;

    while(hasMore)
    {
        string out_r;

        //Receive and display response from destination
        //if(!MessageHandler::getInstance()->recvMsg((char *)&recvMsg))
        if(!MessageHandler::getInstance()->recvMsgNoWait((char *)&recvMsg))
        {
            cout << "NO response received." << endl;
            return;
        }
   
        PCMDHEADER pCmd = (PCMDHEADER) ((char*)&recvMsg + sizeof(MSGHEADER));

        decode(pCmd, out_r);

        cout << out_r << endl;
    }

    return;
}

void* ModuleGsm::rcvSnifferResultflow(void* pVoid)
{
    ModuleGsm *pModGsm = (ModuleGsm *)pVoid;
    pModGsm->handleSnifferResultMessage();

    return pModGsm;
}

bool ModuleGsm::createRcvSnifferResultThread()
{
    return pthread_create(&tid, NULL, rcvSnifferResultflow, this) == 0;
}

ModuleCdma::ModuleCdma():Module(MODULE_CDMA_CAP, "cdma")
{
    createCmd(MODULE_CDMA_CAP, CMD_SET, CMD_CDMA_RESET,           "reset", "Reset cdma module.");    
    createCmd(MODULE_CDMA_CAP, CMD_SET, CMD_CDMA_WIRELESS_OFF,      "stop", "Usage: stop [<carrierIdx [0|1]>].");    
    createCmd(MODULE_CDMA_CAP, CMD_SET, CMD_CDMA_WIRELESS_ON,       "start", "Usage: start [<carrierIdx [0|1]>].");    
    createCmd(MODULE_CDMA_CAP, CMD_SET, CMD_CDMA_DO_SNIFFER,    "dosniffer", "Request cdma module to sniffer.");    
    createCmd(MODULE_CDMA_CAP, CMD_GET, CMD_CDMA_GET_MODULE_STATUS, "status", "Get cdma module status.");
    createCmd(MODULE_CDMA_CAP, CMD_SET, CMD_CDMA_TX_ATTUATION,  "settxatt", "Usage: settxatt <attuation (0~90 dB)>.");
}

bool ModuleCdma::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool result = false;

    len = 0;
    switch(cmdCode)
    {
        case CMD_CDMA_RESET:
        case CMD_CDMA_WIRELESS_OFF:
        case CMD_CDMA_WIRELESS_ON:
        case CMD_CDMA_DO_SNIFFER:
        case CMD_CDMA_GET_MODULE_STATUS:
            result = true;
            break;
        case CMD_CDMA_TX_ATTUATION:
            result = buildSetCdmaTxAttuation(params, payload, len);
            break;
        default:
            cout << __func__ << "  Unknown cmdCode: " << cmdCode << endl;              
            break;
    }

    return result;
}

bool ModuleCdma::buildSetCdmaTxAttuation(vector<string> &params, char *payload, U16 &len)
{
    int attuation = 0;

    if (params.size() < 2)
    {
        cout << "Parameter number should be 2" << endl;
        return false;
    }

    attuation = atoi(params[1].c_str());

    if(attuation > 90 || attuation <= 0)
    {
        cout << "attuation should be larger than 0, and smaller or equal than 90" << endl;
        return false;
    }

    len = packMsg1Param(PARA_TYPE_CDMA_TX_ATTUATION, 4,  (U8 *)&attuation , payload);

    return true;
}

bool ModuleCdma::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;

    bool rc = false;

    switch(pCmd->cmdCode)
    {
        case CMD_CDMA_RESET:
        case CMD_CDMA_WIRELESS_OFF:
        case CMD_CDMA_WIRELESS_ON:
        case CMD_CDMA_DO_SNIFFER:
        case CMD_CDMA_TX_ATTUATION:
            rc = decodeGeneralCmdResponse(pCmd, out_r);
            break;            

        case CMD_CDMA_GET_MODULE_STATUS:
            rc = decodeGetCdmaMOduleStatus(pCmd, out_r);
            break;
        default:
            oss << __func__ << " Unknown cmdCode:" << pCmd->cmdCode << endl;
            break;
    } 

    out_r += oss.str();
    return rc;
}

bool ModuleCdma::decodeGetCdmaMOduleStatus(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_CDMA_MODULE_STATUS:
                 oss << "CDMA Module State: " << paraValue << endl;
                 break;
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;                 
        }

    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

ModulePa::ModulePa():Module(MODULE_PA, "pa")
{
    createCmd(MODULE_PA, CMD_SET, CMD_CODE_PA_SWITCH_OFF, "poweroff", "Usage: poweroff <paId (1~11)>.");
    createCmd(MODULE_PA, CMD_SET, CMD_CODE_PA_SWITCH_ON, "poweron", "Usage: poweron <paId (1~11)>.");
    createCmd(MODULE_PA, CMD_SET, CMD_CODE_PA_RESET, "reset", "Usage: reset <paId (1~11)>.");
    createCmd(MODULE_PA, CMD_SET, CMD_CODE_UP_ATT, "setupatt", "Usage: setupatt <paId (1~11)> <upatt>.");
    createCmd(MODULE_PA, CMD_SET, CMD_CODE_DN_ATT, "setdnatt", "Usage: setdnatt <paId (1~11)> <dnatt>.");
	createCmd(MODULE_PA, CMD_SET, CMD_CODE_TEMP_THRESHOLD, "settempthreshold", "Usage: settempthreshold <paId (1~11)> <temp>.");
	createCmd(MODULE_PA, CMD_SET, CMD_CODE_POWER_THRESHOLD, "setpowerthreshold", "Usage: setpowerthreshold <paId (1~11)> <temp>.");
    createCmd(MODULE_PA, CMD_SET, CMD_CODE_SYSMONITOR_TEST_MODULE, "TestModulePA", "this module is one thread");
//    createCmd(MODULE_PA, CMD_GET, CMD_CODE_GET_PA_SW_VER, "getsw_ver", "usage:getsw_ver paId<1~7>.");
    createCmd(MODULE_PA, CMD_GET, CMD_CODE_GET_PA_SWITCH, "getswitch", "usage:getswitch paId<1~11>.");
    createCmd(MODULE_PA, CMD_GET, CMD_CODE_GET_PA_TEMP, "gettemp", "usage:gettemp paId<1~11>.");
    createCmd(MODULE_PA, CMD_GET, CMD_CODE_GET_PA_UP_ATT, "getupatt", "usage:getupatt paId<1~11>.");
    createCmd(MODULE_PA, CMD_GET, CMD_CODE_GET_PA_DN_ATT, "getdnatt", "usage:getdnatt paId<1~11>.");
    createCmd(MODULE_PA, CMD_GET, CMD_CODE_GET_PA_DN_POWER, "getdnpower", "usage:getdnpower paId<1~11>.");
    createCmd(MODULE_PA, CMD_GET, CMD_CODE_GET_PA_DN_10_POWER, "getdn10power", "usage:getdn10power paId<1~11>.");
    createCmd(MODULE_PA, CMD_GET, CMD_CODE_GET_PA_STATE, "getpastate", "usage:getpastate paId<1~11>."); 
    createCmd(MODULE_PA, CMD_GET, CMD_CODE_GET_PA_10_SWR, "getpa10swr", "usage:getpa10swr paId<1~11>.");
	createCmd(MODULE_PA, CMD_GET, CMD_CODE_GET_TEMP_THRESHOLD, "gettempthreshold", "usage:gettempthreshold paId<1~11>.");
	createCmd(MODULE_PA, CMD_GET, CMD_CODE_GET_POWER_THRESHOLD, "getpowerthreshold", "usage:getpowerthreshold paId<1~11>.");
}

bool ModulePa::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
	bool result = false;
    len = 0;
    switch(cmdCode)
    {
        case CMD_CODE_PA_SWITCH_OFF:
        case CMD_CODE_PA_SWITCH_ON:
        case CMD_CODE_PA_RESET:
            result = buildSetPaState(params, payload, len);
            break;

		case CMD_CODE_UP_ATT:
            result = buildSetPaUpatt(params, payload, len);
            break;    
        case CMD_CODE_DN_ATT:
            result = buildSetPaDnatt(params, payload, len);
            break;
		case CMD_CODE_TEMP_THRESHOLD:
			result = buildSetPaTempthreshold(params, payload, len);
            break;
		case CMD_CODE_POWER_THRESHOLD:
			result = buildSetPaPowerthreshold(params, payload, len);
            break;
        case CMD_CODE_SYSMONITOR_TEST_MODULE:
            result = true;
            break;
  
      	case CMD_CODE_GET_PA_SWITCH:
		case CMD_CODE_GET_PA_TEMP:
  		case CMD_CODE_GET_PA_UP_ATT:
  		case CMD_CODE_GET_PA_DN_ATT:
		case CMD_CODE_GET_PA_DN_POWER:
		case CMD_CODE_GET_PA_DN_10_POWER:
   		case CMD_CODE_GET_PA_STATE:
    	case CMD_CODE_GET_PA_10_SWR:
		case CMD_CODE_GET_TEMP_THRESHOLD:
		case CMD_CODE_GET_POWER_THRESHOLD:
            result = buildGetPaStatus(params, payload, len);            
            break;

		default:
            break;
    }

    return result;
}

bool ModulePa::buildSetPaState(vector<string> &params, char *payload, U16 &len)
{
    U8 paId = 0;

    if(params.size() >= 2)
    {
        paId = (U8)atoi(params[1].c_str());
        len = packMsg1Param(PARA_TYPE_PA_ADDR, 1, (U8 *)&paId, payload);
    }
  	cout << "paId"<<static_cast<uint32_t>(paId) <<endl;	 
    if((paId < 1) || (paId > 11))
    {
        cout << "PA id should be 1 to 11" <<endl;
        return false;
    }

    return true;
}

bool ModulePa::buildGetPaStatus(vector<string> &params, char *payload, U16 &len)
{
    U8 paId = 0;

    if (params.size() >= 2)
    {
        paId = (U8)atoi(params[1].c_str());
    }
  	cout << "paId"<<static_cast<uint32_t>(paId) <<endl;	 
	if ((paId < 1) || (paId > 11))
    {
        cout << "PA ID should be  1 to 11" << endl;
        return false;
    }

    len = packMsg1Param(PARA_TYPE_PA_ADDR, 1, (U8 *)&paId, payload);

    return true;
}



bool ModulePa::buildSetPaUpatt(vector<string> &params, char *payload, U16 &len)
{
    U32 i = 0;
    U8 upatt[1] = {0};
    U8 paId = 0;

    if (params.size() < 3)
    {
        cout << "Usage: setupatt <paId (1~11)> <upatt>." << endl;
        return false;
    }

    //paID
    paId = (U8)atoi(params[++i].c_str());
    if ((paId < 1) || (paId > 11))
    {
        cout << "PA ID should be  1 to 11" << endl;
        return false;
    }

    upatt[0] = (U8)atoi(params[++i].c_str());

    len = packMsg2Param(PARA_TYPE_PA_ADDR, 1, (U8 *)&paId, PARA_TYPE_UP_ATT, 1, (U8 *)upatt, payload);

    return true;
}

bool ModulePa::buildSetPaDnatt(vector<string> &params, char *payload, U16 &len)
{
    U32 i = 0;
    U8 dnatt[1] = {0};
    U8 paId = 0;

    if (params.size() < 3)
    {
        cout << "Usage: setdnatt <paId (1~11)> <dnatt>." << endl;
        return false;
    }

    //paID
    paId = (U8)atoi(params[++i].c_str());
    if ((paId < 1) || (paId > 11))
    {
        cout << "PA ID should be  1 to 11" << endl;
        return false;
    }

    
    dnatt[0] = (U8)atoi(params[++i].c_str());

    len = packMsg2Param(PARA_TYPE_PA_ADDR, 1, (U8 *)&paId, PARA_TYPE_DN_ATT, 1, (U8 *)dnatt, payload);

    return true;
}


bool ModulePa::buildSetPaTempthreshold(vector<string> &params, char *payload, U16 &len)
{
    U32 i = 0;
    U8 temp[1] = {0};
    U8 paId = 0;

    if (params.size() < 3)
    {
        cout << "Usage: settempthreshold <paId (1~11)> <tempthreshold>." << endl;
        return false;
    }

    //paID
    paId = (U8)atoi(params[++i].c_str());
    if ((paId < 1) || (paId > 11))
    {
        cout << "PA ID should be  1 to 11" << endl;
        return false;
    }

    
    temp[0] = (U8)atoi(params[++i].c_str());

    len = packMsg2Param(PARA_TYPE_PA_ADDR, 1, (U8 *)&paId, PARA_TYPE_PA_TEMP_THRESHOLD, 1, (U8 *)temp, payload);

    return true;
}

bool ModulePa::buildSetPaPowerthreshold(vector<string> &params, char *payload, U16 &len)
{
    U32 i = 0;
    U8 power[1] = {0};
    U8 paId = 0;

    if (params.size() < 3)
    {
        cout << "Usage: setpowerthreshold <paId (1~11)> <powerthreshold>." << endl;
        return false;
    }

    //paID
    paId = (U8)atoi(params[++i].c_str());
    if ((paId < 1) || (paId > 11))
    {
        cout << "PA ID should be  1 to 11" << endl;
        return false;
    }

    
    power[0] = (U8)atoi(params[++i].c_str());

    len = packMsg2Param(PARA_TYPE_PA_ADDR, 1, (U8 *)&paId, PARA_TYPE_PA_POWER_THRESHOLD, 1, (U8 *)power, payload);

    return true;
}

bool ModulePa::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    
    bool result = false;
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_PA_SWITCH_OFF:
        case CMD_CODE_PA_SWITCH_ON:
        case CMD_CODE_PA_RESET:
	    case CMD_CODE_UP_ATT:
	    case CMD_CODE_DN_ATT:	
		case CMD_CODE_TEMP_THRESHOLD:
		case CMD_CODE_POWER_THRESHOLD:
            result = decodeGeneralCmdResponse(pCmd, out_r);
            break;
	
        case CMD_CODE_GET_PA_SWITCH:
	    case CMD_CODE_GET_PA_TEMP:
  	    case CMD_CODE_GET_PA_UP_ATT:
  	    case CMD_CODE_GET_PA_DN_ATT:
	    case CMD_CODE_GET_PA_DN_POWER:
	    case CMD_CODE_GET_PA_DN_10_POWER:
   	    case CMD_CODE_GET_PA_STATE:
    	case CMD_CODE_GET_PA_10_SWR:
		case CMD_CODE_GET_TEMP_THRESHOLD:
		case CMD_CODE_GET_POWER_THRESHOLD:

            result = decodeGeneralPaInfoMsg(pCmd, out_r);
            break;
        default:
            break;
    }

    return result;
}

bool ModulePa::decodeGeneralPaInfoMsg(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
	     case PARA_TYPE_PA_SWITCH:
                oss << matchStringValue(paState, *((U32 *)paraValue)) << endl;
                break; 	
		
            case PARA_TYPE_PA_TEMP:
                 oss << "PA Temperature: " << (U32)(*paraValue) << " degree" << endl;
                 break;


            case PARA_TYPE_UP_ATT:
                 oss << "PA UP_ATT: " << (U32)((*paraValue)*0.5) << endl;
                 break; 
    
            case PARA_TYPE_DN_ATT:
                 oss << "PA DN_ATT: " << (U32)((*paraValue)*0.5) << endl;
                 break;

            case PARA_TYPE_PA_DN_POWER:
                 oss << "PA Dn_Power:" << ((*(int8_t *)paraValue)|0x00) << endl;
                 break;
           
            case PARA_TYPE_PA_DN_10_POWER:
                 oss << "PA Dn10Power: " << ((*(int16_t *)paraValue)) << endl;
                 break; 
				 
            case PARA_TYPE_PA_STATE:
                 oss << "PA State: " << (U32)(*paraValue) << endl;
                 break;

            case PARA_TYPE_PA_10_SWR:
                 oss << "PA SW10Radio: " << (U32)(*paraValue) << endl;
                 break;

            case PARA_TYPE_PA_TEMP_THRESHOLD:
                 oss << "PA Tempthreshold: " << (U32)(*paraValue) << endl;
                 break;
				 
			case PARA_TYPE_PA_POWER_THRESHOLD:
			 	 oss << "PA Powerthreshold: " << (U32)(*paraValue) << endl;
				 break;

            case PARA_TYPE_ERROR_CODE:
                 oss << ", failure cause: " << matchStringValue(errorInfo, *((U32 *)paraValue)) << endl; 
                 break;

            case PARA_TYPE_RESULT:
                 oss << matchStringValue(operationResult, *((U32 *)paraValue));
                 break;

            case PARA_TYPE_PA_ADDR:
                 oss << "PA ID: " << (int) (*paraValue) << endl;
                 break; 
            default:
                 oss << __func__ << " Unknown result type: " << paraType << endl;
                 break;
        }    

    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();

    return true;

}



ModuleData::ModuleData():Module(MODULE_DATAPRO, "data")
{
    createCmd(MODULE_DATAPRO, CMD_GET, 0xffff, "status", "Get Data processor Module status.");    
    createCmd(MODULE_DATAM, CMD_SET, CMD_CODE_PHONE_INFO_TRANSFER_STOP, "stopshow", "stop to show phone info (IMSI/IMEI/TMSI).");
    createCmd(MODULE_DATAM, CMD_SET, CMD_CODE_PHONE_INFO_TRANSFER_START, "showphone", "Usage: showphone <start (Y-M-D H:M:S) > <end (Y-M-D H:M:S) > <numPerMsg(default:1)>. Or\n\t\t\t\tshowphone last <minutes>");
    createCmd(MODULE_DATAPRO, CMD_SET, CMD_CODE_BLACKLIST_CONFIG, "setblack", "Usage: setblack <del | add> <imsi | imei> <imsi(number) | imei(number)>.");
    createCmd(MODULE_DATAPRO, CMD_SET, CMD_CODE_WHITELIST_CONFIG, "setwhite", "Usage: setwhite <del | add> <imsi | imei> <imsi(number) | imei(number)>.");
    createCmd(MODULE_DATAM, CMD_SET, CMD_CODE_OBSOLETE_PHONE_INFO, "cleanData", "Usage: cleanData");


    createCmd(MODULE_DATAPRO, CMD_SET, CMD_CODE_SYSMONITOR_TEST_MODULE, "TestModuleDataPro", "this module is one thread");

    createCmd(MODULE_DATAM, CMD_SET, CMD_CODE_SYSMONITOR_TEST_MODULE, "TestModuleDataM", "this module is one thread");
}

bool ModuleData::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool result = false;
    len = 0;
    switch(cmdCode)
    {
        case CMD_CODE_BLACKLIST_CONFIG:
        case CMD_CODE_WHITELIST_CONFIG:
            result = buildSetBWListCfg(params, payload, len);
            break;
        case CMD_CODE_PHONE_INFO_TRANSFER_START:
            result = buildStartShowPhoneInfo(params, payload, len);
            if (result) createRcvPhoneInfoThread();
            break;
        case CMD_CODE_PHONE_INFO_TRANSFER_STOP:
            //stop phone info receiving thread
            hasMore = false;
            result =true;
            break;
        case CMD_CODE_PHONE_INFO_DATA:
            result = true;
            break;

        case CMD_CODE_SYSMONITOR_TEST_MODULE:
            result= true;
            break;

        case CMD_CODE_OBSOLETE_PHONE_INFO:
            result = buildCleanData(payload, len);
            break;

        case 0xffff:
            sleep(1);
            cout << "Data Process Module Status: Running." << endl;
            result = false;
            break;
        default:
            break;
    }

    return result;
}

bool ModuleData::buildCleanData(char *payload, U16 &len)
{
    U32 step = 1;
    len = packMsg1Param(PARA_TYPE_DATASTOR_OBSOLETE_STEPS, sizeof(U32), (U8 *)&step, payload);
    return true;

}

bool ModuleData::buildStartShowPhoneInfo(vector<string> &params, char *payload, U16 &len)
{
    const char * pFormat = "%Y-%m-%d %H:%M:%S";
    string start;
    string end;
    string blank = " ";

    struct tm tmStart, tmEnd;

    U64 utcStart, utcEnd;
    int numPerMsg = 1;
    int minutes = 0;

    //if retrieve all phone info
    //but we need be very careful
    if(params.size() == 1)
    {
        return true;
    }

    if(params[1].compare("last") == 0)
    {
        if(params.size() < 3)
        {
            cout << "missing parameters, usage: showphone last <minutes>" << endl;
            return false;
        }

        minutes = (int)atoi(params[2].c_str());
        if (minutes <= 0)
        {
            cout << "Time should larger than 0" << endl;
            return false;
        }
        else
        {
           cout << "Get last " << minutes << " minutes IMSI/IMEI info" << endl;
        }

        /* 1. get system time */
        utcEnd = (U64)time(NULL);

        utcStart = utcEnd - minutes * 60;
        
        len = packMsg2Param(PARA_TYPE_DATASTOR_BEGIN_TIME, 8, (U8 *)&utcStart, PARA_TYPE_DATASTOR_END_TIME, 8, (U8 *)&utcEnd, payload);

        return true;
    }

    if( params.size() < 5 ) 
    {
        cout << "Input parameter number should be larger or equal than 5" << endl;
        return false;
    }

    int i = 1;

    start = params[i++] + blank;
    start += params[i++];
    end = params[i++] + blank; 
    end += params[i++];

    strptime(start.c_str(), pFormat, &tmStart);
    strptime(end.c_str(), pFormat, &tmEnd);

    utcStart = (U64)mktime(&tmStart);
    utcEnd = (U64)mktime(&tmEnd);


#if 0
    struct tm *timeInfo;
    char buffer[64] = {0};
    timeInfo = localtime((const time_t *)&utcStart);

    strftime(buffer, 64, pFormat, timeInfo);
    cout << buffer << endl;
    cout << utcStart << "   " << utcEnd << endl;
#endif 

    if(utcEnd < utcStart)
    {
        printf("End time should be larger than start time \n");
        return false;
    }

    if(params.size() == 6) 
    {
        numPerMsg = atoi(params[i].c_str());
        if(numPerMsg > 50 || numPerMsg < 1)
        {
            cout << "number of records per message should be between 1 and 50" << endl;
            cout << "set to default value (1)" <<  endl;
            numPerMsg = 1;
        }
    }

    if(params.size() == 5)
    {
        len = packMsg2Param(PARA_TYPE_DATASTOR_BEGIN_TIME, 8, (U8 *)&utcStart, PARA_TYPE_DATASTOR_END_TIME, 8, (U8 *)&utcEnd, payload);
    }
    else if (params.size() == 6)
    {
        len = packMsg3Param(PARA_TYPE_DATASTOR_BEGIN_TIME, 8, (U8 *)&utcStart, PARA_TYPE_DATASTOR_END_TIME, 8, (U8 *)&utcEnd, 
                            PARA_TYPE_DATASTOR_NUM_RECORDS_PER_MESSAGE, 4, (U8 *)&numPerMsg, payload);
    }
    else
    {
        cout << "two many parameters" << endl;
        cout << "Usage: showphone <start (Y-M-D H:M:S) > <end (Y-M-D H:M:S) > <numPerMsg(defaut:1)>." << endl;
        return false;
    }

    return true;
}

bool ModuleData::buildSetBWListCfg(vector<string> &params, char *payload, U16 &len)
{
    U32 action;
    U32 ueIdType; 
    string ueid("\0");

    int i = 1;

    if(params[i].compare("del") == 0)
    {
        action = PARA_VALUE_DATAPROC_ACTION_DEL;
    }
    else if(params[i].compare("add") == 0)
    {
        action = PARA_VALUE_DATAPROC_ACTION_ADD;
    }
    else
    {
        printf("Action should be del or add \n");
        return false;
    }

    i++;
    if(params[i].compare("imsi") == 0)
    {
        ueIdType = PARA_TYPE_DATAPROC_RECORD_IMSI;
    }
    else if(params[i].compare("imei") == 0)
    {
        ueIdType = PARA_TYPE_DATAPROC_RECORD_IMEI;
    }
    else
    {
        printf("UE ID type should be imsi or imei \n");
        return false;
    }

    i++;
   
    ueid = params[i] + ueid;

    len = packMsg2Param(PARA_TYPE_DATAPROC_LIST_ACTION, 4,  (U8 *)&action, ueIdType, 16, (U8 *)(ueid.c_str()), payload);

    return true;
}

bool ModuleData::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;

    bool result = false;
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_BLACKLIST_CONFIG:
        case CMD_CODE_WHITELIST_CONFIG:
            result = decodeGeneralCmdResponse(pCmd, out_r);
            break;
        case CMD_CODE_PHONE_INFO_TRANSFER_START:
        case CMD_CODE_PHONE_INFO_TRANSFER_STOP: 
            result = decodePhoneInfoCmdResponse(pCmd, out_r);
            break;
        case CMD_CODE_PHONE_INFO_DATA:
            result = decodePhoneInfoData(pCmd, out_r);
            break;

        case CMD_CODE_OBSOLETE_PHONE_INFO:
            result = decodeGeneralCmdResponse(pCmd, out_r);
            break;
        default:
            oss << "Unknown CmdCode:" << pCmd->cmdCode << endl;
            out_r += oss.str();
            break;
    }

    return result;
}

bool ModuleData::decodePhoneInfoCmdResponse(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_RESULT:
                 oss << matchStringValue(operationResult, *((U32 *)paraValue)) << endl;

                 if ((pCmd->cmdCode == CMD_CODE_PHONE_INFO_TRANSFER_START) && 
                     ((*((U32 *)paraValue)) != PARA_VALUE_RESULT_SUCCESS))
                 {
                     hasMore = false;
                 }

                 break;
            case PARA_TYPE_ERROR_CODE:
                 //stop phone info receiving thread since there is something wrong happened
                 hasMore = false;
                 oss << ", failure cause: " << matchStringValue(errorInfo, *((U32 *)paraValue)) << endl; 
                 break;
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;
        }

    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}


bool ModuleData::decodePhoneInfoData(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    phoneInfo_t phone;

    const char * pFormat = "%Y-%m-%d.%H:%M:%S";
    char tmBuffer[64] = {0};
    struct tm* tmTemp;
    bool delay = false;
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_DATASTOR_PHONE_INFO:
                 phone.uptime = *((U64*)paraValue);
                 phone.slotId = *((int *)paraValue + 2);
                 phone.imsi = paraValue + sizeof(U64) + sizeof(int);
                 phone.imei = phone.imsi + strlen((const char *)phone.imsi) + 1;

                 tmTemp = localtime((time_t*)&(phone.uptime));
                 strftime(tmBuffer, 64, pFormat, tmTemp);

                 //calc the total record numbers 
                 recordNum++;

                 oss << tmBuffer <<" "<< phone.slotId<< " " << phone.imsi << " " << phone.imei << endl;
                 break;
            case PARA_TYPE_DATASTOR_HAS_MORE_DATA:
                if(*(U32 *)paraValue == 0)
                {
                    //if no phone info data anymore, stop receiving thread
                    hasMore = false;
                    delay = true;
                }
                else
                {
                    sendPhoneInfoAck(CMD_EVENT_RESPONSE, CMD_CODE_PHONE_INFO_DATA);
                }
                break;
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;                 
        }

    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    if(delay)
    {
        oss << endl;
        oss << "Total Phone Records: " << recordNum << endl;
    }

    out_r += oss.str();
    return true;
}

void ModuleData::sendPhoneInfoAck(U16 cmdType, U16 cmdCode)
{
    vector<string> params;

    // Step1: Initialize Messaage Header and Command Header
    sentMsg.msgHeader_m.srcID = MODULE_CLI;
    sentMsg.msgHeader_m.dstID = MODULE_DATAM;
    sentMsg.msgHeader_m.mType = get_mtype(sentMsg.msgHeader_m.dstID);
    sentMsg.msgHeader_m.msgType = MSG_TYPE_COMMAND;

    sentMsg.cmdHeader_m.cmdType = cmdType;
    sentMsg.cmdHeader_m.cmdCode = cmdCode;
    sentMsg.cmdHeader_m.cmdIndex = 0;
    
    // Step2: Build Command Payload
    if(!encode(cmdCode, params, sentMsg.cmdPayload_m, sentMsg.cmdHeader_m.cmdLength))
    {
        return;
    }

    sentMsg.msgHeader_m.msgLength = sizeof(MSGHEADER) + sizeof(CMDHEADER) + sentMsg.cmdHeader_m.cmdLength;

    // Step3: Send message to destination and wait for response
    if( ! MessageHandler::getInstance()->sendMsg((char *)&sentMsg, 
        sentMsg.msgHeader_m.msgLength) )
    {
        cout << __func__ << ": Can NOT sent message to module: " << name_m << endl;
        return;
    }
}

void ModuleData::handlePhoneInfoMessage()
{
    hasMore = true;
    recordNum = 0;
    ostringstream oss;

    while(hasMore)
    //while(1)
    {
        string out_r;

        // Step4: Receive and display response from destination
        //if(!MessageHandler::getInstance()->recvMsg((char *)&recvMsg))
        if(!MessageHandler::getInstance()->recvMsgNoWait((char *)&recvMsg))
        {
            cout << "NO response received." << endl;
            return;
        }

#if 0            
        printf("receiving ....\n");
        for ( int i = 0; i < 64; i++)
        {
            if(i % 8 == 0 && i != 0) printf("\n");

            printf("%02x ", *((char *)&recvMsg + sizeof(MSGHEADER + i));
        }
        printf("\n");
#endif          
        PCMDHEADER pCmd = (PCMDHEADER) ((char*)&recvMsg + sizeof(MSGHEADER));

        decode(pCmd, out_r);

        cout << out_r << endl;
    }

    return;
}

void* ModuleData::rcvPhoneInfoDataflow(void* pVoid)
{
    ModuleData *pModData = (ModuleData *)pVoid;
    pModData->handlePhoneInfoMessage();

    return pModData;
}

bool ModuleData::createRcvPhoneInfoThread()
{
    return pthread_create(&tid, NULL, rcvPhoneInfoDataflow, this) == 0;
}

ModuleSystem::ModuleSystem():Module(MODULE_SYSTEM, "system")
{
    createCmd(MODULE_SYSTEM, CMD_GET, CMD_CODE_BASIC_INFO, "info", "get system info.");
    createCmd(MODULE_SYSTEM, CMD_GET, CMD_CODE_SYS_STATUS, "status", "get system status.");
    createCmd(MODULE_SYSTEM, CMD_SET, CMD_CODE_SYS_SLEEP, "sleep", "system sleep.");
    createCmd(MODULE_SYSTEM, CMD_SET, CMD_CODE_SYS_WAKE, "wakeup", "system wake up.");
    createCmd(MODULE_SYSTEM, CMD_SET, CMD_CODE_SYS_REBOOT, "reboot", "reboot system.");
    createCmd(MODULE_SYSTEM, CMD_SET, CMD_CODE_SYS_TIME_SYNC, "synctime", "Usage: synctime <time [%Y-%m-%d %H:%M:%S]>.");
    createCmd(MODULE_SYSTEM, CMD_SET, CMD_CODE_LOG_LEVEL, "loglevel", "Usage: loglevel <level [1~7]>.");
    createCmd(MODULE_SYSTEM, CMD_SET, CMD_CODE_DEBUG_LEVEL, "debuglevel", "Usage: debuglevel <level [1~7]>.");    
    createCmd(MODULE_SYSTEM, CMD_SET, CMD_CODE_SYS_SSH_ON, "sshOn", "Usage: sshOn <port user password serverAddr>");   
    createCmd(MODULE_SYSTEM, CMD_SET, CMD_CODE_SYS_SSH_OFF, "sshOff", "stop ssh");
    createCmd(MODULE_SYSTEM, CMD_SET, CMD_CODE_SYSMONITOR_TEST_MODULE, "TestModulesystem", "this module is one thread");  

}

bool ModuleSystem::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool result = false;
    len = 0;
    switch(cmdCode)
    {
        case CMD_CODE_BASIC_INFO:
        case CMD_CODE_SYS_STATUS:
            result = true;
            break;
        case CMD_CODE_SYS_SLEEP:
        case CMD_CODE_SYS_WAKE:
        case CMD_CODE_SYS_REBOOT:
        case CMD_CODE_SYSMONITOR_TEST_MODULE:
        case CMD_CODE_SYS_SSH_OFF:
            result = true;
            break;
        case CMD_CODE_SYS_TIME_SYNC:
            result = setSystemTime(params, payload, len);
            break;
        case CMD_CODE_LOG_LEVEL:
            result = setSystemLogLevel(params, payload, len);
            break;
        case CMD_CODE_DEBUG_LEVEL:
            result = setSystemDebugLevel(params, payload, len);
            break;

        case CMD_CODE_SYS_SSH_ON:
            result = setSystemRemoteSsh(params, payload, len);
            break; 

        default:
            break;
    }
    return result;
}



bool ModuleSystem::setSystemTime(vector<string> &params, char *payload, U16 &len)
{
    const char * pFormat = "%Y-%m-%d %H:%M:%S";
    string time;
    string blank = " ";

    struct tm tmTime;

    U64 utcTime;

    //if retrieve all phone info
    //but we need be very careful
    if(params.size() < 3)
    {
        cout << "Missing parameters, Usage:synctime <time [%Y-%m-%d %H:%M:%S]>" << endl; 
        return false;
    }

    int i = 1;

    time = params[i++] + blank;
    time += params[i++];

    strptime(time.c_str(), pFormat, &tmTime);

    utcTime = (U64)mktime(&tmTime);

#if 0
    struct tm *timeInfo;
    char buffer[64] = {0};
    timeInfo = localtime((const time_t *)&utcTime);

    strftime(buffer, 64, pFormat, timeInfo);
    cout << buffer << endl;
    cout << utcTime << endl;
#endif 

    len = packMsg1Param(PARA_TYPE_TIMESTAMP, 8, (U8 *)&utcTime, payload);
    
    return true;    
}

bool ModuleSystem::setSystemLogLevel(vector<string> &params, char *payload, U16 &len)
{
    U32 i = 0;
    U32 logLevel = 0;

    if (params.size() < 2)
    {
        cout << "Usage: loglevel <level [1~7]>." << endl;
        return false;
    }

    logLevel = atoi(params[++i].c_str());

    if (logLevel > 7)
    {
        cout << "Log level should be less than 7 " << endl;
        return false;
    }

    len = packMsg1Param(PARA_TYPE_SYS_LOG_LEVEL, 4, (U8 *)&logLevel, payload);

    return true;
}

bool ModuleSystem::setSystemDebugLevel(vector<string> &params, char *payload, U16 &len)
{
    U32 i = 0;
    U32 debugLevel = 0;

    if (params.size() < 2)
    {
        cout << "Usage: loglevel <level [0~4]>." << endl;
        return false;
    }

    debugLevel = (U64)atoi(params[++i].c_str());

    if (debugLevel > 7)
    {
        cout << "Log level should be less than 7 " << endl;
        return false;
    }

    len = packMsg1Param(PARA_TYPE_SYS_DEBUG_LEVEL, 4, (U8 *)&debugLevel, payload);

    return true;
}

bool ModuleSystem::setSystemRemoteSsh(vector<string> &params, char *payload, U16 &len)
{

    if (params.size() < 5)
    {
        cout << "Usage: two few argument." << endl;
        return false;
    }

    char* tmpPtr = payload;
    U16 tmpLen = 0;

    tmpLen = packMsg1Param(PARA_TYPE_SYS_REMOTE_SSH_PORT, params[1].length(), (U8 *)params[1].c_str(), tmpPtr);
    len += tmpLen;
    tmpPtr += tmpLen;

    tmpLen = packMsg1Param(PARA_TYPE_SYS_REMOTE_SSH_USER, params[2].length(), (U8 *)params[2].c_str(), tmpPtr);
    len += tmpLen;
    tmpPtr += tmpLen;

    tmpLen = packMsg1Param(PARA_TYPE_SYS_REMOTE_SSH_PASSWORD, params[3].length(), (U8 *)params[3].c_str(), tmpPtr);
    len += tmpLen;
    tmpPtr += tmpLen;

    tmpLen = packMsg1Param(PARA_TYPE_SYS_REMOTE_SSH_SERVERIP, params[4].length(), (U8 *)params[4].c_str(), tmpPtr);
    len += tmpLen;
    tmpPtr += tmpLen;
    return true;
}


bool ModuleSystem::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;

    bool result = false;
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_BASIC_INFO:
        case CMD_CODE_SYS_STATUS:            
            result = decodeSystemInformation(pCmd, out_r);
            break;
        case CMD_CODE_SYS_SLEEP:
        case CMD_CODE_SYS_WAKE:
        case CMD_CODE_SYS_REBOOT: 
        case CMD_CODE_SYS_TIME_SYNC:
        case CMD_CODE_LOG_LEVEL:
        case CMD_CODE_DEBUG_LEVEL:
        case CMD_CODE_SYS_SSH_ON:
        case CMD_CODE_SYS_SSH_OFF:
            result = decodeGeneralCmdResponse(pCmd, out_r);
            break;
        default:
            oss << "Unknown CmdCode:" << pCmd->cmdCode << endl;
            out_r += oss.str();
            break;
    }

    return result;
}

bool ModuleSystem::decodeSystemInformation(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    GPSPOSITION *pGps = NULL; 
    PASTATUS * paStatus;

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_RESULT:
                 oss << matchStringValue(operationResult, *((U32 *)paraValue));
                 break;
            case PARA_TYPE_ERROR_CODE:
                 oss << ", failure cause: " << matchStringValue(errorInfo, *((U32 *)paraValue)) << endl; 
                 break;
            case PARA_TYPE_SYS_SW_VERSION:
                 oss << "Software Version: " << paraValue << endl;
                 break;
            case PARA_TYPE_SYS_DEVICE_TYPE:
                 oss << "Device Type: " << paraValue << endl;
                 break;                 
            case PARA_TYPE_SYS_SW_BUILDDATE:
                 oss << "Software Build Date: " << paraValue << endl;
                 break;                 
            case PARA_TYPE_SYS_SW_BUILDTIME:
                 oss << "Software Build Time: " << paraValue << endl;
                 break;                 
            case PARA_TYPE_SYS_SW_COMPILER_VERSION:
                 oss << "Software Compiler Version: " << paraValue << endl;
                 break;
            case PARA_TYPE_SYS_CPU_USAGE:
                 oss << "CPU Usage: " << *((U32 *)paraValue) << " Percent" << endl;
                 break;
            case PARA_TYPE_SYS_MEM_USAGE:
                 oss << "MEM Usage: " << *((U32 *)paraValue) << " Percent" << endl;
                 break;
            case PARA_TYPE_DATA_STORAGE_USAGE:
                 oss << "Disk Usage: " << *((U32 *)paraValue) << " Percent" << endl;
                 break;
            case PARA_TYPE_GSM_WILELESS_STATE:
                 oss << "Wireless Status: " << matchStringValue(wirelessState, *((U32 *)paraValue)) << endl;
                 break;
            case PARA_TYPE_GSM_SNIFFER_STATE:
                 oss << "Sniffer Status: " << matchStringValue(snifferState, *((U32 *)paraValue)) << endl;
                 break;
            case PARA_TYPE_GPS_COORDINATE:
                 pGps = (GPSPOSITION *) paraValue;
                 oss << "GPS Info: " << endl;
                 oss << "  Longitude: " << setprecision(10) << (double)pGps->longitude << endl; 
                 oss << "  Latitude: " << setprecision(10) << (double)pGps->latitude << endl; 
                 oss << "  Altitude: " << setprecision(10) << (double)pGps->altitude << endl;
                 break;
            case PARA_TYPE_GPS_STATUS:
                 oss << "GPS Status: " << matchStringValue(gpsState, *((U32 *)paraValue)) << endl;                 
                 break;
            case PARA_TYPE_SYS_TEMPERATURE:
                 oss << "system temperature: " << *(S32 *)paraValue << " degree" << endl;
                 break;
            case PARA_TYPE_SYS_PASTATUS:
                 paStatus = (PASTATUS *)paraValue;
                 oss << "PA " << (int)paStatus->ID << " status:" << endl;
                 oss << "   temperature: " << (int)paStatus->temp << endl;
                 oss << "   10SWR: " << (int)paStatus->sw10ratio << endl;
                 oss << "   upatt: " << (int)paStatus->upatt << endl;
                 oss << "   dnatt: " << (int)paStatus->dnatt << endl;
                 oss << "   dn_power: " << (int)paStatus->dn_power << endl;
                 oss << "   dn_10_power: " << (int)paStatus->dn_10_power << endl;
                 break;
            case PARA_TYPE_SYS_MAC_ADDR:
                 oss << "WAN MAC address: " << hex << setfill('0') << setw(2) << (unsigned int)(*(paraValue + 0)) << ":"  
                                            << hex << setfill('0') << setw(2) << (unsigned int)(*(paraValue + 1)) << ":" 
                                            << hex << setfill('0') << setw(2) << (unsigned int)(*(paraValue + 2)) << ":" 
                                            << hex << setfill('0') << setw(2) << (unsigned int)(*(paraValue + 3)) << ":" 
                                            << hex << setfill('0') << setw(2) << (unsigned int)(*(paraValue + 4)) << ":" 
                                            << hex << setfill('0') << setw(2) << (unsigned int)(*(paraValue + 5)) << endl; 
                 break;
            default:
                 oss << __func__ << "Unknown result type: " << paraType << endl;
                 break;
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;

}


ModulePower::ModulePower():Module(MODULE_PM, "power")
{
#ifdef NEW_POWER
    createCmd(MODULE_PM, CMD_SET, CMD_CODE_PM_SHUTDOWN, "shutdown","shutdown <1> <2> <3> ... <16>");
    createCmd(MODULE_PM, CMD_SET, CMD_CODE_PM_RESTART, "restart", "restart <1> <2> <3> ... <16>");
    createCmd(MODULE_PM, CMD_SET, CMD_CODE_PM_POWERON, "poweron", "poweron <1> <2> <3> ... <16>");
#else
    createCmd(MODULE_PM, CMD_SET, CMD_CODE_PM_SHUTDOWN, "shutdown", "shutdown <1> <2> <3> ... <16>");
    createCmd(MODULE_PM, CMD_SET, CMD_CODE_PM_RESTART, "restart", "restart <1> <2> <3> ... <16>");
    createCmd(MODULE_PM, CMD_SET, CMD_CODE_PM_POWERON, "poweron", "poweron <1> <2> <3> ... <16>");
#endif
    createCmd(MODULE_PM, CMD_SET, CMD_CODE_PM_REBOOT_DEVICE, "rebootDevice", "reboot device.");
    createCmd(MODULE_PM, CMD_SET, CMD_CODE_PM_RESET_GPS, "resetgps", "reset gps module.");
    createCmd(MODULE_PM, CMD_GET, 0x0cff, "status", "show power mgr status.");
    createCmd(MODULE_PM, CMD_SET, CMD_CODE_SYSMONITOR_TEST_MODULE, "TestModulePM", "this module is one thread"); 

}

bool ModulePower::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool result = false;
    len = 0;
    switch(cmdCode)
    {
        case CMD_CODE_PM_SHUTDOWN:
            result = encodePowerMgrShutdownModule(params, payload, len);
            break;
        case CMD_CODE_PM_RESTART:
            result = encodePowerMgrRestartModule(params, payload, len);
            break;
        case CMD_CODE_PM_POWERON:
            result = encodePowerMgrPoweronModule(params, payload, len);
            break;
        case CMD_CODE_SYSMONITOR_TEST_MODULE:
        case CMD_CODE_PM_RESET_GPS:
        case CMD_CODE_PM_REBOOT_DEVICE:
            result = true;
            break;
        case 0x0cff:
            cout << "Power Status: Normal" << endl;
            result = false;
            break;
        default:
            break;
    }

    return result;
}

bool ModulePower::encodePowerMgrPoweronModule(vector<string> &params, char *payload, U16 &len)
{
    U8  i = 1;
    U8  moduleId = 0;
#ifdef NEW_POWER
	if (params.size() < 2)
    {
        cout << "Usage: poweron <1> <2> <3> ... <16>"<< endl;
        return false;
    }
    cout<<params.size()<<endl;
    for (; i < params.size(); i++)
    {
        moduleId = atoi(params[i].c_str());
        cout<<"bbuId =="<<moduleId<<atoi(params[i].c_str())<<endl;
	   
	   	if ( (moduleId < 1) || (moduleId > 16))
           return false;
      	len += packMsg1Param(PARA_TYPE_PM_GPIO_CTRL_PIN, sizeof(U8), (U8 *)&moduleId, payload);        
    }
#else
    if (params.size() < 2)
    {
        cout << "Usage: poweron <1> <2> <3> ... <16>" << endl;
        return false;
    }
    cout<<params.size()<<endl;
    for (; i < params.size(); i++)
    {

        moduleId = atoi(params[i].c_str());
        cout<<"num =="<<moduleId<<atoi(params[i].c_str())<<endl;
        if ( (moduleId < 1) || (moduleId > 16))
           return false;
        len += packMsg1Param(PARA_TYPE_PM_GPIO_CTRL_PIN, sizeof(U8), (U8 *)&moduleId, payload);        
    }
#endif 
    return true;
}

bool ModulePower::encodePowerMgrShutdownModule(vector<string> &params, char *payload, U16 &len)
{
    U8  i = 1;
    U8  moduleId = 0;
#ifdef NEW_POWER
	if (params.size() < 2)
    {
        cout << "Usage: poweron <1> <2> <3> ... <16>" << endl;
        return false;
    }
    cout<<params.size()<<endl;
    for (; i < params.size(); i++)
    {
        moduleId = atoi(params[i].c_str());
        cout<<"bbuId =="<<moduleId<<atoi(params[i].c_str())<<endl;
	   	if ( (moduleId < 1) || (moduleId > 16))
           return false;
      len += packMsg1Param(PARA_TYPE_PM_GPIO_CTRL_PIN, sizeof(U8), (U8 *)&moduleId, payload);       
	}
#else
    if (params.size() < 2)
    {
        cout << "Usage: poweron <1> <2> <3> ... <16>" << endl;
        return false;
    }
    for (; i < params.size(); i++)
    {

        moduleId = atoi(params[i].c_str());
       cout<<"num =="<<moduleId<<atoi(params[i].c_str())<<endl;
        if ( (moduleId < 1) || (moduleId > 16))
           return false;
        len += packMsg1Param(PARA_TYPE_PM_GPIO_CTRL_PIN, sizeof(U8), (U8 *)&moduleId, payload);        
    } 
#endif
    return true;
}

bool ModulePower::encodePowerMgrRestartModule(vector<string> &params, char *payload, U16 &len)
{
    U8  i = 1;
	U8  moduleId = 0;
#ifdef NEW_POWER
	if (params.size() < 2)
    {
        cout << "Usage: poweron <1> <2> <3> ... <16>" << endl;
        return false;
    }
    cout<<params.size()<<endl;
    for (; i < params.size(); i++)
    {
        moduleId = atoi(params[i].c_str());
        cout<<"bbuId =="<<moduleId<<atoi(params[i].c_str())<<endl;
	   	if ( (moduleId < 1) || (moduleId > 16))
           return false;
      	len += packMsg1Param(PARA_TYPE_PM_GPIO_CTRL_PIN, sizeof(U8), (U8 *)&moduleId, payload); 
	}
#else
    if (params.size() < 2)
    {
        cout << "Usage: poweron <1> <2> <3> ... <16>" << endl;
        return false;
    }
    for (; i < params.size(); i++)
    {

        moduleId = atoi(params[i].c_str());
       cout<<"num =="<<moduleId<<atoi(params[i].c_str())<<endl;
        if ( (moduleId < 1) || (moduleId > 16))
           return false;
        len += packMsg1Param(PARA_TYPE_PM_GPIO_CTRL_PIN, sizeof(U8), (U8 *)&moduleId, payload);        
    } 
#endif
    return true;
} 

bool ModulePower::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    
    bool result = false;
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_PM_POWERON:
        case CMD_CODE_PM_SHUTDOWN:
        case CMD_CODE_PM_RESTART:
        case CMD_CODE_PM_RESET_GPS:
        case CMD_CODE_PM_REBOOT_DEVICE:
            result = decodeGeneralCmdResponse(pCmd, out_r);
            break;
        default:
            oss << "Unknown CmdCode:" << pCmd->cmdCode << endl;
            out_r += oss.str();
            break;
    }

    return result;
}

ModuleGps::ModuleGps():Module(MODULE_GPS, "gps")
{
    createCmd(MODULE_GPS, CMD_GET, CMD_CODE_GPS_STATUS, "status", "get gps status.");
    createCmd(MODULE_GPS, CMD_SET, CMD_CODE_SYSMONITOR_TEST_MODULE, "TestModuleGPS", "this module is one thread");
}

bool ModuleGps::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool result = false;
    len = 0;
    switch(cmdCode)
    {
        case CMD_CODE_GPS_STATUS:
        case CMD_CODE_SYSMONITOR_TEST_MODULE:
            result = true;
            break;
        default:
            break;
    }
    return result;
}

bool ModuleGps::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    
    bool result = false;
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_GPS_STATUS:
            result = decodeGpsStatus(pCmd, out_r);
            break;
        default:
            oss << "Unknown CmdCode:" << pCmd->cmdCode << endl;
            out_r += oss.str();
            break;
    }

    return true;
}

bool ModuleGps::decodeGpsStatus(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    GPSPOSITION *pGps = NULL; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_RESULT:
                 oss << matchStringValue(operationResult, *((U32 *)paraValue));
                 break;
            case PARA_TYPE_ERROR_CODE:
                 oss << ", failure cause: " << matchStringValue(errorInfo, *((U32 *)paraValue)) << endl; 
                 break;
            case PARA_TYPE_GPS_STATUS:
                 oss << "GPS Status: " << matchStringValue(gpsState, *((U32 *)paraValue)) << endl;
                 break;
            case PARA_TYPE_GPS_COORDINATE:
                 pGps = (GPSPOSITION *) paraValue;
                 oss << "GPS Info: " << endl;
                 oss << "  Longitude: " << setprecision(10) << (double)pGps->longitude << endl; 
                 oss << "  Latitude: " << setprecision(10) << (double)pGps->latitude << endl; 
                 oss << "  Altitude: " << setprecision(10) << (double)pGps->altitude << endl;
                 break;                 
            default:
                 oss << __func__ << "Unknown result type: " << paraType << endl;
                 break;
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

ModuleMessage::ModuleMessage():Module(MODULE_MESSAGE, "msg")
{
    createCmd(MODULE_MESSAGE, CMD_SET, CMD_CODE_SYSMONITOR_TEST_MODULE, "TestModuleMessage", "this module is one thread");
}

bool ModuleMessage::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool result = false;
    len = 0;
    switch(cmdCode)
    {
        case CMD_CODE_SYSMONITOR_TEST_MODULE:
            result = true;
            break;
        default:
            break;
    }
    return result;
}

bool ModuleMessage::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    
    switch(pCmd->cmdCode)
    {
        default:
            oss << "Unknown CmdCode:" << pCmd->cmdCode << endl;
            out_r += oss.str();
            break;
    }

    return true;
}

ModuleFwmgr::ModuleFwmgr():Module(MODULE_FWMGR, "fwmgr")
{
    createCmd(MODULE_FWMGR, CMD_SET, CMD_CODE_SYS_UPGRADE, "upgrade", "usage: upgrade <url> <md5sum>.");    
    createCmd(MODULE_FWMGR, CMD_SET, CMD_CODE_FWM_INSTALL, "install", "usage: install <pkg_name>.");
    createCmd(MODULE_FWMGR, CMD_SET, CMD_CODE_SYSMONITOR_TEST_MODULE, "TestModuleFWMGR", "this module is one thread");
}

bool ModuleFwmgr::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool result = false;
    switch(cmdCode)
    {
        case CMD_CODE_SYS_UPGRADE:
            result = sendFwmgrUpgradeCommand(params, payload, len);
            break;
        
        case CMD_CODE_FWM_INSTALL:
            result = sendFwmgrInstallCommand(params, payload, len);
            break;

        case CMD_CODE_SYSMONITOR_TEST_MODULE:
            result = true;
            break;

        default:
            break;
    }
    return result;
}

bool ModuleFwmgr::sendFwmgrInstallCommand(vector<string> &params, char *payload, U16 &len)
{
    if(params.size() < 2)
    {
        cout << "Usage: install <pkg_name> " << endl;
        return false;
    }
    
    cout << params[1] << endl;
    len = packMsg1Param(PARA_TYPE_SYS_UPGRADE_PKG, params[1].length(), (U8 *)params[1].c_str(), payload);
    return true;
}

bool ModuleFwmgr::sendFwmgrUpgradeCommand(vector<string> &params, char *payload, U16 &len)
{
     if(params.size() < 3 )
     {
         cout << "Usage: upgrade <url> <md5sum> " << endl;
         return false;
     }

     if(params[2].length() != 32)
     {
         cout << "MD5sum should be 32 bytes" << endl;
         return false;
     }

     cout << params[1] << params[2] << endl;

     len = packMsg2Param(PARA_TYPE_SYS_UPGRADE_URL, params[1].length(), (U8 *)params[1].c_str(), 
                         PARA_TYPE_SYS_UPGRADE_MD5SUM, params[2].length(), (U8 *)params[2].c_str(), payload);

     return true;
}

bool ModuleFwmgr::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    
    bool result = false;
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_SYS_UPGRADE:
            result = decodeGeneralCmdResponse(pCmd, out_r);
            break;
        
        case CMD_CODE_FWM_INSTALL:
            result = decodeGeneralCmdResponse(pCmd, out_r);
            break;

        default:
            oss << "Unknown CmdCode:" << pCmd->cmdCode << endl;
            out_r += oss.str();
            break;
    }

    return true;    
}

ModuleWifi::ModuleWifi():Module(MODULE_WIFI, "wifi")
{
    createCmd(MODULE_WIFI, CMD_GET, CMD_WIFI_GET_MODULE_STATUS, "status", "Show Wifi Status.");    
    createCmd(MODULE_WIFI, CMD_SET, CMD_WIFI_WIRELESS_OFF, "wifion", "set wifi on.");  
    createCmd(MODULE_WIFI, CMD_SET, CMD_WIFI_WIRELESS_ON, "wifioff", "set wifi off.");    
}

bool ModuleWifi::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool result = false;
    switch(cmdCode)
    {
        case CMD_WIFI_WIRELESS_ON:
		case CMD_WIFI_WIRELESS_OFF:
		case CMD_WIFI_GET_MODULE_STATUS:	
            result = true;
            break;
        default:
            break;
    }
    return result;
}

bool ModuleWifi::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    
    bool result = false;
    switch(pCmd->cmdCode)
    {
        case CMD_WIFI_WIRELESS_ON:
        case CMD_WIFI_WIRELESS_OFF:
            result = decodeGeneralCmdResponse(pCmd, out_r);
            break;
			
		case CMD_WIFI_GET_MODULE_STATUS:
			result = decodeGetWifiModuleStatus(pCmd, out_r);
			break;

        default:
            oss << "Unknown CmdCode:" << pCmd->cmdCode << endl;
            out_r += oss.str();
            break;
    }

    return true;   

}

bool ModuleWifi::decodeGetWifiModuleStatus(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_WIFI_MODULE_STATUS:
                 oss << "Wifi Module State: " << paraValue << endl;
                 break;
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;                 
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

ModuleEutran::ModuleEutran(): Module(MODULE_EUTRAN_SNIFFER, "eutran")
{
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_SET_BBU_IP, "setBbuIp", "usage: addBbu [slot id] [ip address] [port]");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_INIT_CONFIG, "initConfig", "usage: initConfig [slot-id] [10|20] [syncMode] [gpsTmDelay] [saveFS?0:1] [working-band]");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_START_SNIFFER, "startSniff", "usage: startSniff [slot-id] [RSSI] {earfcn=38900-38900} {band=38,40} {pci=2,3} {autoCfg=0|1} {rptResultStrategy=0|1}.");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_GET, CMD_CODE_EUTRAN_GET_SNIFFER_STATUS, "getSniffStatus", "usage: getSnifferStatus");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_STOP_SNIFFER, "stopSniff", "usage: stopSniff");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_RESET_SNIFFER, "resetSniff", "usage: resetSniff");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_CONFIG_RSSI, "configRssiThresold", "usage: configRssiThresold [slot-id] rssi-value");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_GET, CMD_CODE_EUTRAN_GET_SNIFFER_RESULT, "getSnifferResult", "usage: getSnifferResult [slot-id]");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_GET, CMD_CODE_EUTRAN_GET_RSSI, "getRssi", "usage: getRssi");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_UPDATE_CELL, "cellUpdate", "usage: cellUpdate slotId=1 {plmnId=46000} {tac=3000} {earfcn=38900}");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_CONFIG_CELL, "cellConfig", "usage: cellConfig slotId=1 earfcn=38900 pci=300 plmnId=46000 tac=3000 nbrCellPci=2,4,5 interFreq=38950");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_TX_POWER_DB_CONFIG, "txPwDbCfg", "usage: txPwDbCfg slotId=1 txPowerDb=3");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_GET, CMD_CODE_EUTRAN_SOFTWARE_VERSION_REQ, "swVerReq", "usage: swVerReq [slot-id]");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_GET, CMD_CODE_EUTRAN_BBU_STATE_REQ, "reqBbuState", "usage: reqBbuState [slot-id]");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_BBU_REBOOT, "reboot", "usage: reboot [slot-id] [desc]");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_SYNC_MODE_SETTING, "setSyncMode", "usage: setSyncMode [slot-id] [status-code]");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_BBU_UPGRADE, "upgrade", "usage: upgrade [slot-id] [ipaddr] [fileName] [md5] {downMode(0|1)}");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_SYNC_STATE_GET, "getSyncState", "usage: getSyncState [slot-id]");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_GET, CMD_CODE_EUTRAN_SHOW_BBU_INFO, "showBbuInfo", "usage: showBbuInfo");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_LOCATION_MODE_SETTING, "locModeSetting", "usage: locModeSetting [slot-id] [on|off] {IMSI list: 123456789012345;123456789012346}");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_GET, CMD_CODE_EUTRAN_GPS_STATE_REQ, "getGpsState", "usage: getGpsState [slot-id]");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_CFG_AUTO_SNF, "cfgAutoSnf", "usage: cfgAutoSnf [set|del|req] [slot-id] [day(ex:2)] [03:00] [RSSI] [earfcn=38900-38900] {UL=39000}");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_REDIT_CONFIG, "ueRedire", "usage: ueRedire [set|close] [slot-id] [LTE|GERAN|UTRA-FDD|UTRA-TDD|HRPD|1XRTT] {band=38} {arfcnList=[e.x:38000,39000]} {imsiList=[e.x:1234567890abcde;0123456789abcde}");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_STD_TX_POWER_CONFIG, "stdTxPowerCfg", "usage: stdTxPowerCfg [slot-id] [txPower]");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_STD_TX_POWER_GET, "getStdTxPower", "usage: getStdTxPower [slot-id]");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_STD_TX_POWER_DB_GET, "getStdTxPowerDb", "usage: getStdTxPowerDb [slot-id]");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_UEID_FILTER_SWITCH, "setUeIdFilterOn", "usage: setUeIdOn [slot-id] [0|1] {timer}");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_EUTRAN_RT_PARA_CFG, "rtParaCfg", "usage: rtParaCfg [slot-id] [0|1] [0;30] [1;20]");
    createCmd(MODULE_EUTRAN_SNIFFER, CMD_SET, CMD_CODE_SYSMONITOR_TEST_MODULE, "TestModuleEutran", "usage: 0 is EutranMain | 1 is UdpRcv");
}

bool ModuleEutran::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool result = false;
    switch(cmdCode)
    {
        case CMD_CODE_EUTRAN_RT_PARA_CFG:
        {
            result = sendRtParaCfg(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_UEID_FILTER_SWITCH:
        {
            result = sendUeIdFilterSiwtch(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_STD_TX_POWER_CONFIG:
        {
            result = sendStdTxPower(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_STD_TX_POWER_GET:
        {
            result = sendStdTxPowerGet(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_STD_TX_POWER_DB_GET:
        {
            result = sendTxPowerStdDbGet(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_REDIT_CONFIG:
        {
            result = sendUeRedirect(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_CFG_AUTO_SNF:
        {
            result = sendAutoSnfCfgCmd(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_SHOW_BBU_INFO:
        {
            result = sendShowBbuInfo(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_GPS_STATE_REQ:
        {
            result = sendGpsStateReq(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_SYNC_STATE_GET:
        {
            result = sendSyncModeGet(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_SYNC_MODE_SETTING:
        {
            result = sendSyncModeSetting(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_BBU_UPGRADE:
        {
            result = sendBbuUpgrade(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_BBU_REBOOT:
        {
            result = sendBbuRebootReq(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_BBU_STATE_REQ:
        {
            result = sendBbuStateReq(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_SOFTWARE_VERSION_REQ:
        {
            result = sendSoftwareVerReq(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_TX_POWER_DB_CONFIG:
        {
            result = sendTxPowerCfg(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_INIT_CONFIG:
        {
            result = sendInitCfgCmd(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_SET_BBU_IP:
        {
            result = sendSetBbuIpCmd(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_START_SNIFFER:
            result = sendSnifferStartCmd(params, payload, len);
            break;
        case CMD_CODE_EUTRAN_GET_SNIFFER_STATUS:
            result = sendGetSnifferStatusCmd(params, payload, len);
            break;
        case CMD_CODE_EUTRAN_STOP_SNIFFER:
        {
            result = sendSnifferStopCmd(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_RESET_SNIFFER:
        {
            result = sendSnifferResetCmd(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_CONFIG_RSSI:
        {
            result = sendRssiConfigCmd(params, payload, len);
            if( !result )
            {
                printf("Invalid command\n");
            }
            break;
        }
        case CMD_CODE_EUTRAN_GET_SNIFFER_RESULT:
        {
            result = sendGetSnifferResultCmd(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_GET_RSSI:
        {
            result = sendRssiThresholdCmd(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_UPDATE_CELL:
        {
            result = sendCellUpdateCmd(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_CONFIG_CELL:
        {
            result = sendCellConfigCmd(params, payload, len);
            break;
        }
        case CMD_CODE_EUTRAN_LOCATION_MODE_SETTING:
        {
            result = sendLocModeSettingCmd(params, payload, len);
            break;
        }

        case CMD_CODE_SYSMONITOR_TEST_MODULE:
        {
            result = sendModuleTest(params, payload, len);
            break;
        }
        default:
            break;
    }
    return result;
}

bool ModuleEutran::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    
    bool result = false;
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_EUTRAN_RT_PARA_CFG:
        case CMD_CODE_EUTRAN_UEID_FILTER_SWITCH:
        case CMD_CODE_EUTRAN_SYNC_MODE_SETTING:
        case CMD_CODE_EUTRAN_INIT_CONFIG:
        case CMD_CODE_EUTRAN_START_SNIFFER:
        case CMD_CODE_EUTRAN_STOP_SNIFFER:
        case CMD_CODE_EUTRAN_RESET_SNIFFER:
        case CMD_CODE_EUTRAN_CONFIG_RSSI:
        case CMD_CODE_EUTRAN_UPDATE_CELL:
        case CMD_CODE_EUTRAN_CONFIG_CELL:
        case CMD_CODE_EUTRAN_SET_BBU_IP:
        case CMD_CODE_EUTRAN_TX_POWER_DB_CONFIG:
        case CMD_CODE_EUTRAN_BBU_UPGRADE:
        case CMD_CODE_EUTRAN_LOCATION_MODE_SETTING:
        case CMD_CODE_EUTRAN_BBU_REBOOT:
        case CMD_CODE_EUTRAN_REDIT_CONFIG:
        case CMD_CODE_EUTRAN_STD_TX_POWER_CONFIG:
        {
            result = decodeGeneralCmdResponse(pCmd, out_r);
            break;
        }
        case CMD_CODE_EUTRAN_STD_TX_POWER_DB_GET:
        {
            result = decodeStdTxPowerDbGetCmd(pCmd, out_r);
            break;
        }
        case CMD_CODE_EUTRAN_STD_TX_POWER_GET:
        {
            result = decodeStdTxPowerGetCmd(pCmd, out_r);
            break;
        }
        case CMD_CODE_EUTRAN_CFG_AUTO_SNF:
        {
            result = decodeAutoSnfCfgCmd(pCmd, out_r);
            break;
        }
        case CMD_CODE_EUTRAN_GET_SNIFFER_STATUS:
        {
            result = decodeSnifferStatus(pCmd, out_r);
            break;
        }
        case CMD_CODE_EUTRAN_GET_SNIFFER_RESULT:
        {
            result = decodeSnifferResult(pCmd, out_r);
            break;
        }
        case CMD_CODE_EUTRAN_GET_RSSI:
        {
            result = decodeRssiThreshold(pCmd, out_r);
            break;
        }
        case CMD_CODE_EUTRAN_SOFTWARE_VERSION_REQ:
        {
            result = decodeSoftwareVersion(pCmd, out_r);
            break;
        }
        case CMD_CODE_EUTRAN_BBU_STATE_REQ:
        {
            result = decodeBbuStateReq(pCmd, out_r);
            break;
        }
        case CMD_CODE_EUTRAN_SYNC_STATE_GET:
        {
            result = decodeSyncState(pCmd, out_r);
            break;
        }
        case CMD_CODE_EUTRAN_SHOW_BBU_INFO:
        {
            result = decodeShowBbuInfo(pCmd, out_r);
            break;
        }
        case CMD_CODE_EUTRAN_GPS_STATE_REQ:
        {
            result = decodeGpsState(pCmd, out_r);
            break;
        }
        default:
        {
            oss << "Unknown CmdCode:" << pCmd->cmdCode << endl;
            out_r += oss.str();
            break;
        }
    }

    return true;    
}

bool ModuleEutran::sendRtParaCfg(vector<string>& params, char* payload, U16& len)
{
    char* tmpPtr = payload;
    len = 0;
    uint16_t templen = 0;

    templen = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;

    templen = packMsg1Param(PARA_TYPE_EUTRAN_IS_RAN_SHARE, params[2].length(), (U8 *)params[2].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;

    templen = packMsg1Param(PARA_TYPE_EUTRAN_NAS_REJECT_CAUSE_PAIR_STR, params[3].length(), (U8 *)params[3].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;
    
    return true;
}

bool ModuleEutran::sendModuleTest(vector<string>& params, char* payload, U16& len)
{
    if ( params.size() != 2)
    {
        cout << "Invalid command" << std::endl;
        return false;
    }
    U32 thread = 0;
    if ( atoi(params[1].c_str()) == PARA_VALUE_SYSMONITOR_MAIN )
    {        
        thread = PARA_VALUE_SYSMONITOR_MAIN;
    }
    else
    {
        thread = PARA_VALUE_SYSMONITOR_THREAD1;
    }
    len = packMsg1Param( PARA_TYPE_SYSMONITOR_TEST, 4, (U8 *)&thread,
                        payload);
    return true;
}

bool ModuleEutran::sendUeIdFilterSiwtch(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=3 && params.size()!=4 )
    {
        cout << "Invalid command" << std::endl;
        return false;
    }

    if( params.size()==3 )
    {
        len = packMsg2Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(),
                            PARA_TYPE_EUTRAN_UEID_FILTER_SWITCH, params[2].length(), (U8 *)params[2].c_str(),
                            payload);
    }
    else
    {
        len = packMsg3Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(),
                            PARA_TYPE_EUTRAN_UEID_FILTER_SWITCH, params[2].length(), (U8 *)params[2].c_str(),
                            PARA_TYPE_EUTRAN_UEID_FILTER_TIMER, params[3].length(), (U8 *)params[3].c_str(),
                            payload);
    }
    
    return true;
}

bool ModuleEutran::sendTxPowerStdDbGet(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=2 )
    {
        cout << "Invalid command" << std::endl;
        return false;
    }

    len = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(),
                        payload);
    
    return true;
}

bool ModuleEutran::sendStdTxPowerGet(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=2 )
    {
        cout << "Invalid command" << std::endl;
        return false;
    }

    len = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), 
                        payload);
    return true;
}

bool ModuleEutran::sendStdTxPower(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=3 )
    {
        cout << "Invalid command" << std::endl;
        return false;
    }

    len = packMsg2Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), 
                        PARA_TYPE_EUTRAN_STD_TX_POWER, params[2].length(), (U8 *)params[2].c_str(), 
                        payload);
    return true;
}

bool ModuleEutran::sendUeRedirect(vector<string>& params, char* payload, U16& len)
{
    if( params.size()<3 )
    {
        cout << "Invalid command" << std::endl;
        return false;
    }

    if( 0==strcmp(params[1].c_str(), "set") )
    {
        if( params.size()<5 )
        {
            cout << "Invalid command" << std::endl;
            return false;
        }
    }
    else if( 0==strcmp(params[1].c_str(), "close") )
    {
        if( params.size()!=3 )
        {
            cout << "Invalid command" << std::endl;
            return false;
        }
    }

    char* tmpPtr = payload;
    len = 0;
    uint16_t templen = 0;

    if( 0==strcmp(params[1].c_str(), "close") )
    {
        uint32_t opeCode = PARA_VALUE_EUTRAN_UE_REDIRECT_OFF;
        templen = packMsg1Param(PARA_TYPE_EUTRAN_UE_REDIRECT_OPER_CODE, sizeof(opeCode), (U8 *)&opeCode, tmpPtr);
        tmpPtr += templen;
        len += templen;

        templen = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[2].length(), (U8 *)params[2].c_str(), tmpPtr);
        tmpPtr += templen;
        len += templen;

        return true;
    }

    uint32_t opeCode = PARA_VALUE_EUTRAN_UE_REDIRECT_ON;
    templen = packMsg1Param(PARA_TYPE_EUTRAN_UE_REDIRECT_OPER_CODE, sizeof(opeCode), (U8 *)&opeCode, tmpPtr);
    tmpPtr += templen;
    len += templen;

    templen = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[2].length(), (U8 *)params[2].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;

    if( 0==strcmp(params[3].c_str(), "LTE") )
    {
        uint32_t ranCode = PARA_VALUE_RAN_TYPE_LTE;
        templen = packMsg1Param(PARA_TYPE_RAN_TYPE, sizeof(ranCode), (U8 *)&opeCode, tmpPtr);
        tmpPtr += templen;
        len += templen;
    }
    else if( 0==strcmp(params[3].c_str(), "GERAN") )
    {
        uint32_t ranCode = PARA_VALUE_RAN_TYPE_GERAN;
        templen = packMsg1Param(PARA_TYPE_RAN_TYPE, sizeof(ranCode), (U8 *)&opeCode, tmpPtr);
        tmpPtr += templen;
        len += templen;
    }
    else if( 0==strcmp(params[3].c_str(), "UTRA-FDD") )
    {
        uint32_t ranCode = PARA_VALUE_RAN_TYPE_UTRA_FDD;
        templen = packMsg1Param(PARA_TYPE_RAN_TYPE, sizeof(ranCode), (U8 *)&opeCode, tmpPtr);
        tmpPtr += templen;
        len += templen;
    }
    else if( 0==strcmp(params[3].c_str(), "UTRA-TDD") )
    {
        uint32_t ranCode = PARA_VALUE_RAN_TYPE_UTRA_TDD;
        templen = packMsg1Param(PARA_TYPE_RAN_TYPE, sizeof(ranCode), (U8 *)&opeCode, tmpPtr);
        tmpPtr += templen;
        len += templen;
    }
    else if( 0==strcmp(params[3].c_str(), "HRPD") )
    {
        uint32_t ranCode = PARA_VALUE_RAN_TYPE_CDMA2000_HRPD;
        templen = packMsg1Param(PARA_TYPE_RAN_TYPE, sizeof(ranCode), (U8 *)&opeCode, tmpPtr);
        tmpPtr += templen;
        len += templen;
    }
    else if( 0==strcmp(params[3].c_str(), "1XRTT") )
    {
        uint32_t ranCode = PARA_VALUE_RAN_TYPE_CDMA2000_1XRTT;
        templen = packMsg1Param(PARA_TYPE_RAN_TYPE, sizeof(ranCode), (U8 *)&opeCode, tmpPtr);
        tmpPtr += templen;
        len += templen;
    }
    else
    {
        cout << "Invalid command" << endl;
        return false;
    }

    string bandHdrStr = "band=";
    string bandStr;
    string arfcnListHdrStr = "arfcnList=";
    string arfcnListPara;
    string imsiListHdrStr = "imsiList=";
    string imsiListPara;
    for(size_t i=4; i<params.size(); i++)
    {
        if( params[i].compare(0, bandHdrStr.size(), bandHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                bandStr = params[i].substr(loc+1);

                templen = packMsg1Param(PARA_TYPE_EUTRAN_SNIFFER_BAND, bandStr.length(), (U8 *)bandStr.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
            else
            {
                cout << "Invalid command of band";
                return false;
            }
        }
        else if( params[i].compare(0, arfcnListHdrStr.size(), arfcnListHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                arfcnListPara = params[i].substr(loc+1);

                templen = packMsg1Param(PARA_TYPE_EUTRAN_ARFCN_LIST, arfcnListPara.length(), (U8 *)arfcnListPara.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
            else
            {
                cout << "Invalid command of arfcnListPara";
                return false;
            }
        }
        else if( params[i].compare(0, imsiListHdrStr.size(), imsiListHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                imsiListPara = params[i].substr(loc+1);

                templen = packMsg1Param(PARA_TYPE_EUTRAN_LOC_MODE_IMSI_LIST, imsiListPara.length(), (U8 *)imsiListPara.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
            else
            {
                cout << "Invalid command of imsiListPara";
                return false;
            }
        }
    }
    return true;
}

bool ModuleEutran::sendAutoSnfCfgCmd(vector<string>& params, char* payload, U16& len)
{
    if( params.size()<3 )
    {
        cout << "Invalid command" << std::endl;
        return false;
    }

    if( 0==strcmp(params[1].c_str(), "add") )
    {
        if( params.size()!=6 && params.size()!=7 )
        {
            cout << "Invalid command" << std::endl;
            return false;
        }
    }
    else if( 0==strcmp(params[1].c_str(), "del") )
    {
        if( params.size()!=3 )
        {
            cout << "Invalid command" << std::endl;
            return false;
        }
    }
    else if( 0==strcmp(params[1].c_str(), "req") )
    {
        if( params.size()!=3 )
        {
            cout << "Invalid command" << std::endl;
            return false;
        }
    }

    char* tmpPtr = payload;
    len = 0;
    uint16_t templen = 0;

    if( 0==strcmp(params[1].c_str(), "del") )
    {
        uint32_t opeCode = PARA_VALUE_EUTRAN_AUTO_SNF_DEL;
        templen = packMsg1Param(PARA_TYPE_EUTRAN_AUTO_SNF_OPER_CODE, sizeof(opeCode), (U8 *)&opeCode, tmpPtr);
        tmpPtr += templen;
        len += templen;

        templen = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[2].length(), (U8 *)params[2].c_str(), tmpPtr);
        tmpPtr += templen;
        len += templen;

        return true;
    }
    else if( 0==strcmp(params[1].c_str(), "req") )
    {
        uint32_t opeCode = PARA_VALUE_EUTRAN_AUTO_SNF_REQ;
        templen = packMsg1Param(PARA_TYPE_EUTRAN_AUTO_SNF_OPER_CODE, sizeof(opeCode), (U8 *)&opeCode, tmpPtr);
        tmpPtr += templen;
        len += templen;

        templen = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[2].length(), (U8 *)params[2].c_str(), tmpPtr);
        tmpPtr += templen;
        len += templen;
        return true;
    }

    if( !checkTimeFormat(params[4]) )
    {
        cout << "Invalid time: " << params[4] << std::endl;
        return false;
    }

    uint32_t opeCode = PARA_VALUE_EUTRAN_AUTO_SNF_SET;
    templen = packMsg1Param(PARA_TYPE_EUTRAN_AUTO_SNF_OPER_CODE, sizeof(opeCode), (U8 *)&opeCode, tmpPtr);
    tmpPtr += templen;
    len += templen;

    templen = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[2].length(), (U8 *)params[2].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;

    templen = packMsg1Param(PARA_TYPE_EUTRAN_AUTO_SNF_DAY, params[3].length(), (U8 *)params[3].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;

    templen = packMsg1Param(PARA_TYPE_EUTRAN_AUTO_SNF_TIME, params[4].length(), (U8 *)params[4].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;

    templen = packMsg1Param(PARA_TYPE_EUTRAN_SNIFFER_RSSI, params[5].length(), (U8 *)params[5].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;

    std::string earfcnHeadStr = "earfcn=";
    string earfcnPara;
    std::vector<std::pair<uint16_t, uint16_t> > arfcnRangeList;
    if( params[6].compare(0, earfcnHeadStr.size(), earfcnHeadStr)==0 )
    {
        uint32_t loc = params[6].find("=", 0);
        if( loc!=std::string::npos )
        {
            earfcnPara = params[6].substr(loc+1);
            if( !convertToEarfcnList(earfcnPara, arfcnRangeList) )
            {
                cout << "Invalid command " << earfcnPara << std::endl;
                return false;
            }
        }
        else
        {
            cout << "Invalid command " << earfcnPara << std::endl;
            return false;
        }
    }

    if( !arfcnRangeList.empty() )
    {
        uint16_t* buf = new uint16_t[arfcnRangeList.size()*2];
        if( buf==NULL )
        {
            cout << "Fail to allocate buffer" << endl;
            return false;
        }
        for(size_t i=0, j=0; i<arfcnRangeList.size(); i++)
        {
            buf[j++] = arfcnRangeList[i].first;
            buf[j++] = arfcnRangeList[i].second;
        }
        templen = packMsg1Param(PARA_TYPE_EUTRAN_SNIFFER_EARFCN_RANGE, arfcnRangeList.size()*(2*sizeof(uint16_t)), (uint8_t*)buf, tmpPtr);
        tmpPtr += templen;
        len += templen;

        delete [] buf;
        buf = NULL;
    }

    if( params.size()==8 )
    {
        templen = packMsg1Param(PARA_TYPE_EUTRAN_UL_ARFCN, params[7].length(), (U8 *)params[7].c_str(), tmpPtr);
        tmpPtr += templen;
        len += templen;
    }
    return true;
}

bool ModuleEutran::checkTimeFormat(const std::string& para)
{
    // e.x: 03:00
    if( para.size()!=5 )
    {
        return false;
    }

    std::string hour(para.c_str(), 2);
    uint8_t hr = atoi(hour.c_str());
    if( hr>23 )
    {
        return false;
    }

    std::string minute(para.c_str()+3, 2);
    uint8_t min = atoi(minute.c_str());
    if( min>59 )
    {
        return false;
    }
    return true;
}

bool ModuleEutran::sendShowBbuInfo(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=1 )
    {
        cout << "Invalid command" << std::endl;
        return false;
    }
    return true;
}

bool ModuleEutran::sendSyncModeSetting(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=3 )
    {
        return false;
    }

    len = packMsg2Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), 
                        PARA_TYPE_EUTRAN_SYNC_MODE_CODE, params[2].length(), (U8 *)params[2].c_str(), 
                        payload);

    return true;
}

bool ModuleEutran::sendGpsStateReq(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=2 )
    {
        return false;
    }

    len = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), 
                        payload);

    return true;
}

bool ModuleEutran::sendSyncModeGet(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=2 )
    {
        return false;
    }

    len = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), 
                        payload);

    return true;
}

bool ModuleEutran::sendBbuUpgrade(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=5 && params.size()!=6)
    {
        cout << "Invalid command\n";
        return false;
    }

    char* tmpPtr = payload;
    U16 tmpLen = 0;

    tmpLen = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), tmpPtr);
    len += tmpLen;
    tmpPtr += tmpLen;

    tmpLen = packMsg1Param(PARA_TYPE_EUTRAN_UPGRADE_IP_ADDR, params[2].length(), (U8 *)params[2].c_str(), tmpPtr);
    len += tmpLen;
    tmpPtr += tmpLen;

    tmpLen = packMsg1Param(PARA_TYPE_EUTRAN_FILE_NAME, params[3].length(), (U8 *)params[3].c_str(), tmpPtr);
    len += tmpLen;
    tmpPtr += tmpLen;

    tmpLen = packMsg1Param(PARA_TYPE_EUTRAN_FILE_MD5, params[4].length(), (U8 *)params[4].c_str(), tmpPtr);
    len += tmpLen;
    tmpPtr += tmpLen;

    if( params.size()==6 )
    {
        tmpLen = packMsg1Param(PARA_TYPE_EUTRAN_UPGRADE_DOWN_MODE, params[5].length(), (U8 *)params[5].c_str(), tmpPtr);
        len += tmpLen;
        tmpPtr += tmpLen;
    }
    
    return true;
}

bool ModuleEutran::sendBbuRebootReq(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=3 )
    {
        cout << "Invalid parameter" << endl;
        return false;
    }

    len = packMsg2Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), 
                        PARA_TYPE_EUTRAN_BBU_REBOOT_DESC_STR, params[2].length(), (U8 *)params[2].c_str(), 
                        payload);

    return true;
}

bool ModuleEutran::sendBbuStateReq(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=2 )
    {
        return false;
    }

    len = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), payload);

    return true;
}

bool ModuleEutran::sendSoftwareVerReq(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=2 )
    {
        return false;
    }

    len = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), payload);

    return true;
}

bool ModuleEutran::sendTxPowerCfg(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=3 )
    {
        printf("Invalid command\n");
        return false;
    }

    char* tmpPtr = payload;
    len = 0;

    string slotIdHdr = "slotId=";
    string txPwHdr = "txPowerDb=";
    string slotIdPara, txPwPara;
    for(size_t i=0; i<params.size(); i++)
    {
        if( params[i].compare(0, slotIdHdr.size(), slotIdHdr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                slotIdPara = params[i].substr(loc+1);

                U32 templen = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, slotIdPara.length(), (U8 *)slotIdPara.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
            else
            {
                cout << "Invalid command of slotIdPara\n";
                return false;
            }
        }
        else if( params[i].compare(0, txPwHdr.size(), txPwHdr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                txPwPara = params[i].substr(loc+1);

                U32 templen = packMsg1Param(PARA_TYPE_EUTRAN_STD_TX_POWER_DB, txPwPara.length(), (U8 *)txPwPara.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
            else
            {
                cout << "Invalid command of txPwPara\n";
                return false;
            }
        }
    }
    
    return true;
}

bool ModuleEutran::sendInitCfgCmd(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=7 )
    {
        printf("Invalid command\n");
        return false;
    }

    char* tmpPtr = payload;
    len = 0;

    U32 templen = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;

    templen = packMsg1Param(PARA_TYPE_EUTRAN_BAND_WIDTH, params[2].length(), (U8 *)params[2].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;

    templen = packMsg1Param(PARA_TYPE_EUTRAN_SNF_SYNC_MODE, params[3].length(), (U8 *)params[3].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;

    templen = packMsg1Param(PARA_TYPE_EUTRAN_SNF_GPS_TM_DELAY, params[4].length(), (U8 *)params[4].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;

    templen = packMsg1Param(PARA_TYPE_EUTRAN_IS_SAVE_FS, params[5].length(), (U8 *)params[5].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;    

    templen = packMsg1Param(PARA_TYPE_EUTRAN_BBU_WORKING_BAND, params[6].length(), (U8 *)params[6].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;  
    return true;
}

bool ModuleEutran::sendSetBbuIpCmd(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=4 )
    {
        printf("Invalid command\n");
        return false;
    }

    len = packMsg3Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), 
                        PARA_TYPE_EUTRAN_BBU_IP, params[2].length(), (U8 *)params[2].c_str(), 
                        PARA_TYPE_EUTRAN_BBU_PORT, params[3].length(), (U8 *)params[3].c_str(), 
                        payload);
    return true;
}

bool ModuleEutran::sendSnifferStartCmd(vector<string>& params, char* payload, U16& len)
{
    if( params.size()<=3 )
    {
        printf("Invalid command\n");
        return false;
    }

    char* tmpPtr = payload;
    len = 0;

    uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_SNIFFER_RSSI, params[2].length(), (U8 *)params[2].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;

    templen = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;

    string bandHeadStr = "band=";
    string earfcnHeadStr = "earfcn=";
    string pciHeadStr = "pci=";
    string autoConfigHeadStr = "autoCfg=";
    string rptStrategy = "rptResultStrategy=";
    string bandPara, earfcnPara, pciListPara, autoCfgPara, rptStrgyPara;
    std::vector<uint8_t> bandList;
    std::vector<std::pair<uint16_t, uint16_t> > arfcnRangeList;
    std::vector<uint16_t> pciList;
    for(size_t i=0; i<params.size(); i++)
    {
        if( params[i].compare(0, rptStrategy.size(), rptStrategy)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                rptStrgyPara = params[i].substr(loc+1);

                if( rptStrgyPara!="0" && rptStrgyPara!="1" )
                {
                    cout << "Invalid command of rptStrgyPara\n";
                    return false;
                }

                templen = packMsg1Param(PARA_TYPE_EUTRAN_RPT_RESULT_STRATEGY, rptStrgyPara.length(), (U8 *)rptStrgyPara.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
            else
            {
                cout << "Invalid command of autoCfg\n";
                return false;
            }
        }
        else if( params[i].compare(0, autoConfigHeadStr.size(), autoConfigHeadStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                autoCfgPara = params[i].substr(loc+1);

                if( autoCfgPara!="0" && autoCfgPara!="1" )
                {
                    cout << "Invalid command of autoCfg\n";
                    return false;
                }

                templen = packMsg1Param(PARA_TYPE_EUTRAN_AUTO_CONFIG_CELL, autoCfgPara.length(), (U8 *)autoCfgPara.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
            else
            {
                cout << "Invalid command of autoCfg\n";
                return false;
            }
        }
        else if( params[i].compare(0, bandHeadStr.size(), bandHeadStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                bandPara = params[i].substr(loc+1);

                if( !convertToBandList(bandPara, bandList) )
                {
                    printf("Invalid command\n");
                    return false;
                }
            }
            else
            {
                printf("Invalid command\n");
                return false;
            }
        }
        else if( params[i].compare(0, earfcnHeadStr.size(), earfcnHeadStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                earfcnPara = params[i].substr(loc+1);
                if( !convertToEarfcnList(earfcnPara, arfcnRangeList) )
                {
                    printf("Invalid command\n");
                    return false;
                }
            }
            else
            {
                printf("Invalid command\n");
                return false;
            }
        }
        else if( params[i].compare(0, pciHeadStr.size(), pciHeadStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                pciListPara = params[i].substr(loc+1);
                if( !convertToPciList(pciListPara, pciList) )
                {
                    printf("Invalid command\n");
                    return false;
                }
            }
            else
            {
                printf("Invalid command\n");
                return false;
            }
        }
    }
    
    if( !bandList.empty() )
    {
        uint8_t* buf = new uint8_t[bandList.size()];
        if( buf==NULL )
        {
            printf("Fail to allocate buffer\n");
            return false;
        }
        for(size_t i=0; i<bandList.size(); i++)
        {
            buf[i] = bandList[i];
        }
        uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_SNIFFER_BAND, bandList.size(), buf, tmpPtr);
        tmpPtr += templen;
        len += templen;

        delete [] buf;
        buf = NULL;
    }
    if( !arfcnRangeList.empty() )
    {
        uint16_t* buf = new uint16_t[arfcnRangeList.size()*2];
        if( buf==NULL )
        {
            printf("Fail to allocate buffer\n");
            return false;
        }
        for(size_t i=0, j=0; i<arfcnRangeList.size(); i++)
        {
            buf[j++] = arfcnRangeList[i].first;
            buf[j++] = arfcnRangeList[i].second;
        }
        uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_SNIFFER_EARFCN_RANGE, arfcnRangeList.size()*(2*sizeof(uint16_t)), (uint8_t*)buf, tmpPtr);
        tmpPtr += templen;
        len += templen;

        delete [] buf;
        buf = NULL;
    }

    if( !pciList.empty() )
    {
        uint16_t* buf = new uint16_t[pciList.size()];
        if( buf==NULL )
        {
            printf("Fail to allocate buffer\n");
            return false;
        }
        for(size_t i=0; i<pciList.size(); i++)
        {
            buf[i] = pciList[i];
        }
        uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_SNIFFER_PCI_LIST, pciList.size()*sizeof(uint16_t), (uint8_t*)buf, tmpPtr);
        tmpPtr += templen;
        len += templen;

        delete [] buf;
        buf = NULL;
    }

    return true;
}

bool ModuleEutran::sendSnifferStopCmd(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=1 )
    {
        return false;
    }

    return true;
}

bool ModuleEutran::sendSnifferResetCmd(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=1 )
    {
        return false;
    }

    return true;
}

bool ModuleEutran::sendGetSnifferResultCmd(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=2 )
    {
        return false;
    }

    len = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), 
                        payload);

    return true;
}

bool ModuleEutran::sendRssiThresholdCmd(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=1 )
    {
        return false;
    }

    return true;
}


bool ModuleEutran::sendGetSnifferStatusCmd(vector<string>& params, char* payload, U16& len)
{
    if( params.size()==1 )
    {
        std::string slotId = "0";
        len = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, slotId.length(), (U8 *)slotId.c_str(), payload);
        return true;
    }
    else if( params.size()==2 )
    {
        len = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(), payload);
    }
    else
    {
        return false;
    }
    
    return true;
}

bool ModuleEutran::sendRssiConfigCmd(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=3 )
    {
        return false;
    }

    len = packMsg2Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(),
                        PARA_TYPE_EUTRAN_SNIFFER_RSSI, params[2].length(), (U8 *)params[2].c_str(),
                        payload);
    return true;
}

bool ModuleEutran::sendCellUpdateCmd(vector<string>& params, char* payload, U16& len)
{
    if( params.size()<3 || params.size()> 5)
    {
        cout << "Invalid parameters\n";
        return false;
    }

    string plmnHdrStr = "plmnId=";
    string tacHdrStr = "tac=";
    string earfcnHdrStr = "earfcn=";
    string slotIdHdrStr = "slotId=";
    string txPowerHdrStr = "txPower";

    char* tmpPtr = payload;
    len = 0;
    
    for(size_t i=1; i<params.size(); i++)
    {
        if( params[i].compare(0, slotIdHdrStr.size(), slotIdHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                string valueStr = params[i].substr(loc+1);
                uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, valueStr.length(), (U8 *)valueStr.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
        }
        else if( params[i].compare(0, txPowerHdrStr.size(), txPowerHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                string valueStr = params[i].substr(loc+1);
                uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_TX_POWER_DB, valueStr.length(), (U8 *)valueStr.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
        }
        else if( params[i].compare(0, plmnHdrStr.size(), plmnHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                string valueStr = params[i].substr(loc+1);
                uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_PLMN_ID, valueStr.length(), (U8 *)valueStr.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
        }
        else if( params[i].compare(0, tacHdrStr.size(), tacHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                string valueStr = params[i].substr(loc+1);
                uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_TAC, valueStr.length(), (U8 *)valueStr.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
        }
        else if( params[i].compare(0, earfcnHdrStr.size(), earfcnHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                string valueStr = params[i].substr(loc+1);
                uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_DL_ARFCN, valueStr.length(), (U8 *)valueStr.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
        }
        else
        {
            cout << "Invaild parameters: " << params[i] << "\n";
            return false;
        }
    }

    return true;
}

bool ModuleEutran::sendCellConfigCmd(vector<string>& params, char* payload, U16& len)
{
    if( params.size()!=8 )
    {
        cout << "Invalid parameters\n";
        return false;
    }

    string plmnHdrStr = "plmnId=";
    string tacHdrStr = "tac=";
    string earfcnHdrStr = "earfcn=";
    string slotIdHdrStr = "slotId=";
    string pciHdrStr = "pci=";
    string nbrCellPciHdrStr = "nbrCellPci=";
    string interFreqHdrStr = "interFreq=";
    string txPwerHdrStr = "txPower=";

    string pciListPara;
    vector<uint16_t> pciList;

    string interFreqListPara;
    vector<uint16_t> interFreqList;

    char* tmpPtr = payload;
    len = 0;
    
    for(size_t i=1; i<params.size(); i++)
    {
        if( params[i].compare(0, slotIdHdrStr.size(), slotIdHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                string valueStr = params[i].substr(loc+1);
                uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, valueStr.length(), (U8 *)valueStr.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
        }
        else if( params[i].compare(0, txPwerHdrStr.size(), txPwerHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                string valueStr = params[i].substr(loc+1);
                uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_TX_POWER_DB, valueStr.length(), (U8 *)valueStr.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
        }
        else if( params[i].compare(0, earfcnHdrStr.size(), earfcnHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                string valueStr = params[i].substr(loc+1);
                uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_DL_ARFCN, valueStr.length(), (U8 *)valueStr.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
        }
        else if( params[i].compare(0, pciHdrStr.size(), pciHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                string valueStr = params[i].substr(loc+1);
                uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_PCI, valueStr.length(), (U8 *)valueStr.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
        }
        else if( params[i].compare(0, plmnHdrStr.size(), plmnHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                string valueStr = params[i].substr(loc+1);
                uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_PLMN_ID, valueStr.length(), (U8 *)valueStr.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
        }
        else if( params[i].compare(0, tacHdrStr.size(), tacHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                string valueStr = params[i].substr(loc+1);
                uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_TAC, valueStr.length(), (U8 *)valueStr.c_str(), tmpPtr);
                tmpPtr += templen;
                len += templen;
            }
        }
        else if( params[i].compare(0, nbrCellPciHdrStr.size(), nbrCellPciHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                pciListPara = params[i].substr(loc+1);
                if( !convertToPciList(pciListPara, pciList) )
                {
                    printf("Invalid command\n");
                    return false;
                }
            }
            else
            {
                printf("Invalid command\n");
                return false;
            }
        }
        else if( params[i].compare(0, interFreqHdrStr.size(), interFreqHdrStr)==0 )
        {
            uint32_t loc = params[i].find("=", 0);
            if( loc!=std::string::npos )
            {
                interFreqListPara = params[i].substr(loc+1);
                if( !convertToU16TypeList(interFreqListPara, interFreqList) )
                {
                    printf("Invalid command\n");
                    return false;
                }
            }
            else
            {
                printf("Invalid command\n");
                return false;
            }
        }
        else
        {
            cout << "Invaild parameters: " << params[i] << "\n";
            return false;
        }
    }

    if( pciList.empty() )
    {
        cout << "Lack of nbrCell pci list" << "\n";
    }

    uint16_t* buf = new uint16_t[pciList.size()];
    if( buf==NULL )
    {
        cout << "Fail to allocate buffer\n";
        return false;
    }

    for(size_t i=0; i<pciList.size(); i++)
    {
        buf[i] = pciList[i];
    }

    uint16_t templen = packMsg1Param(PARA_TYPE_EUTRAN_SNIFFER_PCI_LIST, pciList.size()*sizeof(uint16_t), (uint8_t*)buf, tmpPtr);
    tmpPtr += templen;
    len += templen;

    delete [] buf;
    buf = NULL;

    if( interFreqList.empty() )
    {
        cout << "Lack of interFreqList" << "\n";
    }

    buf = new uint16_t[interFreqList.size()];
    if( buf==NULL )
    {
        cout << "Fail to allocate buffer\n";
        return false;
    }

    for(size_t i=0; i<interFreqList.size(); i++)
    {
        buf[i] = interFreqList[i];
    }

    templen = packMsg1Param(PARA_TYPE_EUTRAN_ARFCN_LIST, interFreqList.size()*sizeof(uint16_t), (uint8_t*)buf, tmpPtr);
    tmpPtr += templen;
    len += templen;

    delete [] buf;
    buf = NULL;

    return true;
}

bool ModuleEutran::sendLocModeSettingCmd(vector<string>& params, char* payload, U16& len)
{
    if( params.size()>4 )
    {
        cout << "Invalid parameters\n";
        return false;
    }

    char* tmpPtr = payload;
    uint16_t templen = packMsg2Param(PARA_TYPE_EUTRAN_BBU_SLOT_ID, params[1].length(), (U8 *)params[1].c_str(),
                        PARA_TYPE_EUTRAN_LOC_MODE_ENABLE, params[2].length(), (U8 *)params[2].c_str(), tmpPtr);
    tmpPtr += templen;
    len += templen;

    if( params.size()==4 )
    {
        templen = packMsg1Param(PARA_TYPE_EUTRAN_LOC_MODE_IMSI_LIST, params[3].length(), (U8 *)params[3].c_str(), tmpPtr);
        tmpPtr += templen;
        len += templen;
    }

    return true;
}

bool ModuleEutran::decodeStdTxPowerDbGetCmd(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_EUTRAN_STD_TX_POWER_DB:
            {
                int8_t* i8Ptr = (int8_t*)paraValue;
                oss << "STD TX power DB: " << static_cast<int32_t>(*i8Ptr) << endl;
                break;
            }
            case PARA_TYPE_RESULT:
            {
                uint32_t* result = (uint32_t*)paraValue;
                oss << "Result: " << *result << endl;
                break;
            }
            default:
            {
                 oss << __func__ << "Unknown result type: " << paraType << endl;
                 break;
            }
        }
    }
    out_r += oss.str();
    return true;
}


bool ModuleEutran::decodeStdTxPowerGetCmd(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_EUTRAN_STD_TX_POWER:
            {
                uint8_t* u8Ptr = (uint8_t*)paraValue;
                oss << "STD TX power: " << static_cast<uint32_t>(*u8Ptr) << endl;
                break;
            }
            case PARA_TYPE_RESULT:
            {
                uint32_t* result = (uint32_t*)paraValue;
                oss << "Result: " << *result << endl;
                break;
            }
            default:
            {
                 oss << __func__ << "Unknown result type: " << paraType << endl;
                 break;
            }
        }
    }
    out_r += oss.str();
    return true;
}

bool ModuleEutran::decodeAutoSnfCfgCmd(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_EUTRAN_AUTO_SNF_INFO_STR:
            {
                string info((char*)paraValue, paraLength);
                oss << info << endl;
                break;
            }
            case PARA_TYPE_RESULT:
            {
                oss << matchStringValue(operationResult, *((U32 *)paraValue)) << endl;
                break;
            }
            default:
            {
                 oss << __func__ << "Unknown result type: " << paraType << endl;
                 break;
            }
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

bool ModuleEutran::decodeShowBbuInfo(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_EUTRAN_BBU_INFO_STR:
            {
                string info((char*)paraValue, paraLength);
                oss << info.c_str() << endl;
                break;
            }
            default:
            {
                 oss << __func__ << "Unknown result type: " << paraType << endl;
                 break;
            }
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

bool ModuleEutran::decodeGpsState(PCMDHEADER pCmd, string & out_r)
{

    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_EUTRAN_GPS_LONGTITUDE:
            {
                float longitude = float((*(uint32_t*)paraValue)/100000);
                oss << "longitude: " << longitude << endl;
                break;
            }
            case PARA_TYPE_EUTRAN_GPS_LATITUDE:
            {
                float latitude = float((*(uint32_t*)paraValue)/100000);
                oss << "laitude: " << latitude << endl;
                break;
            }
            case PARA_TYPE_RESULT:
            {
                uint32_t* result = (uint32_t*)paraValue;
                if (*result != PARA_VALUE_RESULT_SUCCESS)
                {
                    oss << "get gps info failed" << endl;
                }
                else
                {
                    oss << "Gps info is :" << endl;
                }
                break;
            }
            default:
            {
                 oss << __func__ << "Unknown result type: " << paraType << endl;
                 break;
            }
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}


bool ModuleEutran::decodeSyncState(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_EUTRAN_SNIFFER_STATUS:
            {
                oss << matchStringValue(operationResult, *((U32 *)paraValue));
                break;
            }
            case PARA_TYPE_EUTRAN_SYNC_STATE_TYPE_CODE:
            {
                 U32* ptr = (U32 *)paraValue;
                 oss << "TYPE CODE: " << *ptr << endl;
                 break;
            }
            case PARA_TYPE_EUTRAN_SYNC_STATE_CODE:
            {
                 U32* ptr = (U32 *)paraValue;
                 oss << "STATE CODE: " << *ptr << endl;
                 break;
            }
            case PARA_TYPE_EUTRAN_DL_ARFCN:
            {
                uint16_t* u16Ptr = (uint16_t*)paraValue;
                oss << "Sync arfcn: " << *u16Ptr << endl;
                break;
            }
            case PARA_TYPE_EUTRAN_PCI:
            {
                uint16_t* u16Ptr = (uint16_t*)paraValue;
                oss << "Sync PCI: " << *u16Ptr << endl;
                break;
            }
            case PARA_TYPE_EUTRAN_SNIFFER_RSSI:
            {
                uint16_t* u16Ptr = (uint16_t*)paraValue;
                oss << "Sync rssi: " << *u16Ptr << endl;
                break;
            }
            case PARA_TYPE_EUTRAN_TAC:
            {
                uint16_t* u16Ptr = (uint16_t*)paraValue;
                oss << "Sync tac: " << *u16Ptr << endl;
                break;
            }
            default:
            {
                 oss << __func__ << "Unknown result type: " << paraType << endl;
                 break;
            }
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

bool ModuleEutran::decodeSnifferStatus(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_EUTRAN_SNIFFER_STATUS:
                 oss << matchStringValue(eutranSnifferState, *((U32 *)paraValue));
                 break;
            default:
                 oss << __func__ << "Unknown result type: " << paraType << endl;
                 break;
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

bool ModuleEutran::decodeSnifferResult(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_EUTRAN_BBU_SLOT_ID:
            {
                uint32_t* v32Ptr = (U32*)paraValue;
                oss << "Slot Id " << *v32Ptr << endl;
                break;
            }
            case PARA_TYPE_EUTRAN_SNIFFER_EMPTY_RESULT:
            {
                oss << "Empty result\n";
                break;
            }
            case PARA_TYPE_EUTRAN_SNIFFER_BUSY:
            {
                oss << "Sniffer is on going\n";
                break;
            }
            case PARA_TYPE_EUTRAN_SNIFFER_RESULT:
            {
                U32 sizeOfResult = 4*sizeof(U16);
                if( paraValue!=NULL && (paraLength%sizeOfResult==0) )
                {
                    U32 len = paraLength;
                    U8* tmpPtr = paraValue;
                    while( len>=sizeOfResult )
                    {
                        U16 earfcn = 0, pci = 0, tac = 0, rssi = 0;
                        memcpy(&earfcn, tmpPtr, sizeof(earfcn));
                        tmpPtr += sizeof(earfcn);

                        memcpy(&pci, tmpPtr, sizeof(pci));
                        tmpPtr += sizeof(pci);

                        memcpy(&tac, tmpPtr, sizeof(tac));
                        tmpPtr += sizeof(tac);

                        memcpy(&rssi, tmpPtr, sizeof(rssi));
                        tmpPtr += sizeof(rssi);

                        len -= sizeOfResult;

                        oss << "earfcn=" << earfcn << "; pci=" << pci << "; tac=" << tac << "; rssi=" << rssi << "\n";
                    }
                }
                break;
            }
            default:
            {
                 oss << __func__ << "Unknown result type: " << paraType << endl;
                 break;
            }
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

bool ModuleEutran::decodeSoftwareVersion(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        if (paraType==PARA_TYPE_EUTRAN_SOFTWARE_VERSION)
        {
            string version;
            version.assign(reinterpret_cast<char*>(paraValue), paraLength);
            oss << "Software version is " << version << "\n";
        }
        else if (paraType==PARA_TYPE_EUTRAN_PHY_VER)
        {
            string version;
            version.assign(reinterpret_cast<char*>(paraValue), paraLength);
            oss << "Phy version is " << version << "\n";
        }
        else if (paraType==PARA_TYPE_EUTRAN_KERNEL_VER)
        {
            string version;
            version.assign(reinterpret_cast<char*>(paraValue), paraLength);
            oss << "Kernel version is " << version << "\n";
        }
        else if (paraType==PARA_TYPE_EUTRAN_HARDWARE_VER)
        {
            string version;
            version.assign(reinterpret_cast<char*>(paraValue), paraLength);
            oss << "Hardware version is " << version << "\n";
        }
        else if (paraType==PARA_TYPE_RESULT)
        {
            oss << matchStringValue(operationResult, *((U32 *)paraValue));
            break;
        }
        else
        {
            oss << "Invalid command code:" << paraType << "\n";
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

bool ModuleEutran::decodeRssiThreshold(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        if (paraType==PARA_TYPE_EUTRAN_SNIFFER_RSSI)
        {
            U16 rssiThold = 0;
            memcpy(&rssiThold, paraValue, sizeof(U16));

            oss << "RSSI thresold is " << rssiThold << "\n";
        }
        else
        {
            oss << "Invalid command code:" << paraType << "\n";
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

bool ModuleEutran::decodeCellUpdateRsp(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    uint32_t rc = 0;
    uint32_t errCode = 0;

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        if (paraType==PARA_TYPE_RESULT)
        {
            rc = *(reinterpret_cast<uint32_t*>(paraValue));
        }
        else if( paraType==PARA_TYPE_ERROR_CODE )
        {
            errCode = *(reinterpret_cast<uint32_t*>(paraValue));
        }
        else
        {
            oss << "Invalid command code:" << paraType << "\n";
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    if( rc==PARA_VALUE_RESULT_FAILED )
    {
        oss << "Failure: rc=" << errCode << "\n";
    }

    out_r += oss.str();
    return true;
}

bool ModuleEutran::decodeBbuStateReq(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_EUTRAN_BBU_SLOT_ID:
            {
                uint8_t value = *paraValue;
                oss << "BBU-ID: " << static_cast<uint32_t>(value) << "\n";
                break;
            }
            case PARA_TYPE_EUTRAN_BBU_STATE:
            {
                 oss << matchStringValue(eutranBbuState, *((U32 *)paraValue)) << "\n";
                 break;
            }
            case PARA_TYPE_EUTRAN_BBU_STATE_DES_STR:
            {
                string desc;
                desc.assign(reinterpret_cast<char*>(paraValue), paraLength);
                oss << desc << "\n";
                break;
            }
            case PARA_TYPE_EUTRAN_CPU_TEMP:
            {
                uint8_t value = *paraValue;
                oss << "CPU temp: " << static_cast<uint32_t>(value) << "\n";
                break;
            }
            case PARA_TYPE_EUTRAN_CPU_USAGE:
            {
                uint8_t value = *paraValue;
                oss << "CPU usage: " << static_cast<uint32_t>(value) << "\n";
                break;
            }
            case PARA_TYPE_EUTRAN_MEM_USAGE:
            {
                uint8_t value = *paraValue;
                oss << "MEM usage: " << static_cast<uint32_t>(value) << "\n";
                break;
            }
            case PARA_TYPE_EUTRAN_BOARD_TEMP:
            {
                int8_t value = *paraValue;
                oss << "Board temp: " << static_cast<int32_t>(value) << "\n";
                break;
            }
            case PARA_TYPE_RESULT:
            {
                oss << matchStringValue(operationResult, *((U32 *)paraValue));
                oss << "\n";
                break;
            }
            default:
                 oss << __func__ << "Unknown result type: " << paraType << endl;
                 break;
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

bool ModuleEutran::convertToBandList(const std::string& para, std::vector<uint8_t>& bandList)
{
    if( para.empty() )
    {
        printf("para is empty\n");
        return false;
    }
    uint32_t startIndex = 0;
    uint32_t endIndex = 0;
    const char* paraValue = para.c_str();
    
    for(uint32_t i=0; ; i++, endIndex = i)
    {
        if( i==para.length() )
        {
            if( endIndex==startIndex )
            {
                break;
            }
            std::string s(&paraValue[startIndex], endIndex-startIndex);
            uint8_t band = atoi(s.c_str());
            if( band>44 || band < 1 )
            {
                printf("band[%d] is out of range\n", static_cast<uint32_t>(band)); 
                return false;
            }
            bandList.push_back(band);
            break;
        }
        else if( paraValue[i]==',' )
        {
            if( endIndex==startIndex )
            {
                continue;
            }
            std::string s(&paraValue[startIndex], endIndex-startIndex);
            uint16_t band = atoi(s.c_str());
            if( band>44 || band < 1 )
            {
                printf("band[%d] is out of range\n", static_cast<uint32_t>(band)); 
                return false;
            }
            bandList.push_back(band);
            
            startIndex = i+1;
        }
        else if( paraValue[i]>'9' || paraValue[i]<'0' )
        {
            printf("Invalid parameter[%d]: %c\n", i, paraValue[i]);
            return false;
        }
        
    }

    return true;
}

bool ModuleEutran::convertToEarfcnList(const std::string& para, std::vector<std::pair<uint16_t, uint16_t> >& arfcnRangeList)
{
    if( para.empty() )
    {
        printf("parameter is emtpy\n");
        return false;
    }
    uint32_t startIndex = 0;
    uint32_t endIndex = 0;
    uint16_t lowerArfcn = 0, upperArfcn = 0;
    bool isLowerArfcnPresent = false;

    const char* paraValue = para.c_str();
    for(uint32_t i=0; ;i++, endIndex = i)
    {
        if( i==para.length() )
        {
            if( endIndex==startIndex )
            {
                continue;
            }
            std::string s(&paraValue[startIndex], endIndex-startIndex);
            upperArfcn = atoi(s.c_str());
            startIndex = i+1;
            if( lowerArfcn>upperArfcn || !isLowerArfcnPresent)
            {
                printf("Invalid parameter: lowerArfcn=[%d], upperArfcn=[%d]\n", lowerArfcn, upperArfcn);
                return false;
            }
            arfcnRangeList.push_back(std::make_pair<uint16_t, uint16_t>(lowerArfcn, upperArfcn));
            break;
        }
        else if( paraValue[i]=='-' )
        {
            if( endIndex==startIndex )
            {
                continue;
            }
            std::string s(&paraValue[startIndex], endIndex-startIndex);
            lowerArfcn = atoi(s.c_str());
            startIndex = i+1;
            isLowerArfcnPresent = true;
        }
        else if( paraValue[i]==',' )
        {
            if( endIndex==startIndex )
            {
                continue;
            }
            std::string s(&paraValue[startIndex], endIndex-startIndex);
            upperArfcn = atoi(s.c_str());
            startIndex = i+1;
            if( lowerArfcn>upperArfcn || !isLowerArfcnPresent)
            {
                printf("Invalid parameter: lowerArfcn=[%d], upperArfcn=[%d]\n", lowerArfcn, upperArfcn);
                return false;
            }
            arfcnRangeList.push_back(std::make_pair<uint16_t, uint16_t>(lowerArfcn, upperArfcn));
            isLowerArfcnPresent = false;
        }
        else if( paraValue[i]>'9' || paraValue[i]<'0' )
        {
            printf("Invalid parameter[%d]: %c\n", i, paraValue[i]);
            return false;
        }
        
    }
    return true;
}

bool ModuleEutran::convertToU16TypeList(const std::string& para, std::vector<uint16_t>& list)
{
    if( para.empty() )
    {
        printf("para is empty\n");
        return false;
    }
    uint32_t startIndex = 0;
    uint32_t endIndex = 0;
    const char* paraValue = para.c_str();
    for(uint32_t i=0; ;i++, endIndex = i)
    {
        if( i==para.length() )
        {
            if( endIndex==startIndex )
            {
                break;
            }
            std::string s(&paraValue[startIndex], endIndex-startIndex);
            uint16_t v16 = atoi(s.c_str());
            list.push_back(v16);
            break;
        }
        else if( paraValue[i]==',' )
        {
            if( endIndex==startIndex )
            {
                continue;
            }
            std::string s(&paraValue[startIndex], endIndex-startIndex);
            uint16_t v16 = atoi(s.c_str());
            list.push_back(v16);
            
            startIndex = i+1;
        }
        else if( paraValue[i]>'9' || paraValue[i]<'0' )
        {
            printf("Invalid parameter[%d]: %c\n", i, paraValue[i]);
            return false;
        }
        
    }
    return true;
}


bool ModuleEutran::convertToPciList(const std::string& para, std::vector<uint16_t>& pciList)
{
    if( para.empty() )
    {
        printf("para is empty\n");
        return false;
    }
    uint32_t startIndex = 0;
    uint32_t endIndex = 0;
    const char* paraValue = para.c_str();
    for(uint32_t i=0; ;i++, endIndex = i)
    {
        if( i==para.length() )
        {
            if( endIndex==startIndex )
            {
                break;
            }
            std::string s(&paraValue[startIndex], endIndex-startIndex);
            uint16_t pci = atoi(s.c_str());
            if( pci>503 )
            {
                //printf("pci[%d] is out of range\n", pci);
                //return false;
            }
            pciList.push_back(pci);
            break;
        }
        else if( paraValue[i]==',' )
        {
            if( endIndex==startIndex )
            {
                continue;
            }
            std::string s(&paraValue[startIndex], endIndex-startIndex);
            uint16_t pci = atoi(s.c_str());
            if( pci>503 )
            {
                //printf("pci[%d] is out of range\n", pci);
                //return false;
            }
            pciList.push_back(pci);
            
            startIndex = i+1;
        }
        else if( paraValue[i]>'9' || paraValue[i]<'0' )
        {
            printf("Invalid parameter[%d]: %c\n", i, paraValue[i]);
            return false;
        }
        
    }
    return true;
}

ModuleScanner::ModuleScanner():Module(MODULE_SCANNER, "scanner")
{
    createCmd(MODULE_SCANNER, CMD_SET, CMD_LTE_DO_SNIFFER, "scanlte", "set scan lte frequency.");  
    createCmd(MODULE_SCANNER, CMD_SET, CMD_WCDMA_DO_SNIFFER, "scanwcdma", "set scan wcdma frequency.");
    createCmd(MODULE_SCANNER, CMD_SET, CMD_SCANNER_GSM_DO_SNIFFER, "scangsm", "set scan gsm frequency.");
    createCmd(MODULE_SCANNER, CMD_GET, CMD_GET_LTE_RESULT, "lteinfo", "show lte frequency info.");  
    createCmd(MODULE_SCANNER, CMD_GET, CMD_GET_WCDMA_RESULT, "wcdmainfo", "who wcdma frequency info.");

}

bool ModuleScanner::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool result = false;
    switch(cmdCode)
    {
        case CMD_LTE_DO_SNIFFER:
            result = true;
            cout << "Wait about 2 minutes!" << endl;
            break;
		case CMD_WCDMA_DO_SNIFFER:
            result = true;
            cout << "Wait about 1 minutes!" << endl;
            break;
        case CMD_SCANNER_GSM_DO_SNIFFER:
            result = true;
            cout << "Wait about 2 minutes" <<endl;
            break;

        case CMD_GET_LTE_RESULT:
        case CMD_GET_WCDMA_RESULT:
            result = true;
            break;
        default:
            break;
    }
    return result;
}

bool ModuleScanner::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    
    bool result = false;
    switch(pCmd->cmdCode)
    {
        case CMD_LTE_DO_SNIFFER:
        case CMD_WCDMA_DO_SNIFFER:
        case CMD_SCANNER_GSM_DO_SNIFFER:
            result = decodeGeneralCmdResponse(pCmd, out_r);
            break;
        case CMD_GET_LTE_RESULT:
        case CMD_GET_WCDMA_RESULT:
        case CMD_EVT_EUTRAN_SNIFF:
            result = decodeGetSnifferResult(pCmd, out_r);
            break;
        default:
            oss << "Unknown CmdCode:" << pCmd->cmdCode << endl;
            out_r += oss.str();
            break;
    }

    return true;   
}

bool ModuleScanner::decodeGetSnifferResult(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 

    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_SNIFFER_RESULT:
                 if(paraLength > 0)
                 {
                     oss << paraValue << endl;
                 }
				 else
				 {
				     oss << "Error message." << endl;
				 }
				 
                 break;
            case PARA_TYPE_SNIFFER_BUSY:
                 oss << "Sniffer is on going, wait a minutes" << endl;
                 break;
            case PARA_TYPE_NO_NEIGHBOR_CELL:
                 oss << "No neighboring cell " << endl;
                 break;
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;                 
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

ModuleFep::ModuleFep():Module(MODULE_INTF, "fep")
{
     
    createCmd(MODULE_INTF, CMD_SET, CMD_CODE_FEP_LOG_LEVEL, "fep", "Usage: fep loglevel <level [0~7]>.");
    createCmd(MODULE_INTF, CMD_SET, CMD_CODE_FEP_UPGRADE, "upgrade", "usage: upgrade <url> <md5sum>."); 
    createCmd(MODULE_INTF, CMD_SET, CMD_CODE_SYSMONITOR_TEST_MODULE, "TestModuleINTF", "usage: 0 is handleThread | 1 is msgrcv_thread | 2 is cli_rcv_thread");

#if 0
    createCmd(MODULE_INTF, CMD_SET, CMD_CODE_FEP_DO_SNIFFER, "autosniffer", "Usage: rssi= <rssi> frequency=  <lowfreq 1 ~ 6> <upfreq 1 ~ 6>  band= <band 1 ~ 6> pci=  <pci 1 ~ 6> ");
	createCmd(MODULE_INTF, CMD_SET, CMD_CODE_FEP_CONFIG_CELL, "config_cell", "Usage: <cellId> <frequency> <pci> <plmnId> <tac> <pciList> <frequencyList>");
#endif
}

bool ModuleFep::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool result = false;
    len = 0;
    switch(cmdCode)
    {
    
        case CMD_CODE_FEP_LOG_LEVEL:
            result = set_Fep_loglevel(params, payload, len);
            break;
        case CMD_CODE_FEP_UPGRADE:
            result = sendFepUpgradeCommand(params, payload, len);
            break; 	

        case CMD_CODE_SYSMONITOR_TEST_MODULE:
            result = sendModuleTest(params, payload, len);
            break;
#if 0
        case CMD_CODE_FEP_AUTO_SNIFFER:
            result = set_sniffer_request(params, payload, len);
            break;
        case CMD_CODE_FEP_DO_SNIFFER:
            result = set_do_sniffer(params, payload, len);
            break;
        case CMD_CODE_FEP_CONFIG_CELL:
            result = chang_cell(params, payload, len);
			break;
#endif
        default:
            break;
    }
    return result;
}

bool ModuleFep::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    bool result = false;

//  cout<<"pCmd->cmdcode hex:"<<hex <<pCmd->cmdCode<<endl; 
    switch(pCmd->cmdCode)
    {
        case CMD_CODE_FEP_LOG_LEVEL:
            result = decodeGeneralCmdResponse(pCmd, out_r);
            break;

        default:
            oss << "Unknown CmdCode:" << pCmd->cmdCode << endl;
            out_r += oss.str();
            break;
    }
    return result;
}

bool ModuleFep::sendModuleTest(vector<string>& params, char* payload, U16& len)
{
    if ( params.size() != 2)
    {
        cout << "Invalid command" << std::endl;
        return false;
    }
    U32 thread = 0;
    if ( atoi(params[1].c_str()) == PARA_VALUE_SYSMONITOR_MAIN )
    {        
        thread = PARA_VALUE_SYSMONITOR_MAIN;
    }
    else if ( atoi(params[1].c_str()) == PARA_VALUE_SYSMONITOR_THREAD1 )
    {
        thread = PARA_VALUE_SYSMONITOR_THREAD1;
    }
    else
    {
        thread = PARA_VALUE_SYSMONITOR_THREAD2;
    }
    len = packMsg1Param( PARA_TYPE_SYSMONITOR_TEST, 4, (U8 *)&thread,
                        payload);
    return true;

}

bool ModuleFep::sendFepUpgradeCommand(vector<string> &params, char *payload, U16 &len)
{
     if(params.size() < 3 )
     {
         cout << "Usage: upgrade <url> <md5sum> " << endl;
         return false;
     }

     if(params[2].length() != 32)
     {
         cout << "MD5sum should be 32 bytes" << endl;
         return false;
     }

     cout << params[1] << params[2] << endl;

     len = packMsg2Param(PARA_TYPE_SYS_UPGRADE_URL, params[1].length(), (U8 *)params[1].c_str(), 
                         PARA_TYPE_SYS_UPGRADE_MD5SUM, params[2].length(), (U8 *)params[2].c_str(), payload);

     return true;
}


bool ModuleFep::set_Fep_loglevel(vector<string> &params, char *payload, U16 &len)
{
    U32 i = 0;
    U32 logLevel = 0;
    U32 msgTlv[3] = {0};
    U32 dstID = 0x1;

    if (params.size() < 3)
    {
        cout << "Too few inputs" << endl; 
        cout << "Usage: fep loglevel <level [0~7]>." << endl;
        return false;
    }

    if(params[++i].compare("loglevel") != 0)
    {
        cout << "command " << params[i] << " not supported" << endl;
        cout << "Usage: fep loglevel <level [0~7]>." << endl;
        return false; 
    }

    logLevel = atoi(params[++i].c_str());

    if (logLevel > 7)
    {
        cout << "Log level should be less than 7 " << endl;
        return false;
    }

    msgTlv[0] = 0x10000000; //set if_app log level command;
    msgTlv[1] = 4;          //length
    msgTlv[2] = logLevel;   //log level 

    len = packMsg2Param(PARA_TYPE_MSG_FORWARD_DEST, 4, (U8 *)&dstID, 
                        PARA_TYPE_MSG_FORWARD_MSG, 12, (U8 *)&msgTlv[0], payload);

    return true;
}
#if  0
bool ModuleFep::set_sniffer_request(vector<string> &params, char *payuload, U16 &len)
{
	

    return true;
}


bool ModuleFep::chang_cell(vector<string> &params, char *payload, U16 &len)
{
	config_cell cell_t;
	if ( params.size() < 7)
	{
        cout<<"the arguments must more than seven"<<endl;
        cout<<"Usage: <cellId> <frequency> <pci> <plmnId> <tac> <pciList> <frequencyList>"<<endl;
        return false;
	}
	int i = 1 ;
    cell_t.cellid = atoi(params[i++].c_str());
    cell_t.freq = atoi(params[i++].c_str());
	cell_t.pci = atoi(params[i++].c_str());
	cell_t.plmnid = atoi(params[i++].c_str());
	cell_t.tac = atoi(params[i++].c_str());
	cell_t.pciList[0] = atoi(params[i++].c_str());
	cell_t.freqList[0] = atoi(params[i++].c_str());
    cell_t.type = 0;
	cout<<"cellid:"<<cell_t.cellid <<endl;
    cout<<"freq:"<<cell_t.freq<<endl;
	cout<<"pci:"<<cell_t.pci<<endl;
    cout<<"plmnid:"<<cell_t.plmnid<<endl;
    cout<<"tac:"<<cell_t.tac<<endl;
	cout<<"pcilist:"<<cell_t.pciList[0]<<endl;
    cout<<"freqList:"<<cell_t.freqList[0]<<endl;
    len = packMsg1Param(PARA_TYPE_EUTRAN_CONFIG_CELL, sizeof(config_cell), (U8 *)&cell_t, payload);
	return true;
}


bool ModuleFep::set_do_sniffer(vector<string> &params, char *payload, U16 &len)
{
    string bandstr = "band=";
    string freqstr = "frequency=";
    string pcistr = "pci=";
    string rssistr = "rssi=";
    int  num = 0, type = 0;
    size_t  i;
    START_SNIFFER start_sniffer;
    for ( ; i < 6;i++ )
    {
        start_sniffer.band[i] = 0;
        start_sniffer.freq[2 * i] = 0;
        start_sniffer.freq[2 * i + 1] = 0;
        start_sniffer.pci[i] = -1;
        
    }
    start_sniffer.rssi = 50;
	if ( params.size() < 3)
	{
        cout<<"too few input"<<endl;
        cout<<"Usage: rssi= <rssi> frequency=  <lowfreq 1 ~ 6> <upfreq 1 ~ 6>  band= <band 1 ~ 6> pci=  <pci 1 ~ 6>"<<endl;
        return false;
	}
    for (i = 0; i < params.size(); i++ )
    { 
        if (params[i].compare(rssistr) == 0)
            type = 1;  
        if (params[i].compare(freqstr) == 0)
        {
            i++;
            type = 2;
        }
        if (params[i].compare(bandstr) == 0)
        {
            num = 0;
            i++;
            type = 3; 
        }
        if (params[i].compare(pcistr) == 0)
        {
            num = 0;
            i++;
            type = 4; 
        }
        if (type == 1)
        {
            i++;
            start_sniffer.rssi = atoi(params[i].c_str());
        }

        if (type == 2)
        {
            start_sniffer.freq[2 * num] = atoi(params[i++].c_str());
            start_sniffer.freq[2 * num + 1] = atoi(params[i].c_str());
            cout<<start_sniffer.freq[2 * num]<<endl;
            num++;
        }

        if (type == 3)
        {
            start_sniffer.band[num] = atoi(params[i].c_str());
            num ++;
        }

        if (type == 4)
        {
            start_sniffer.pci[num] = atoi(params[i].c_str());
            num ++;
        }
    }
    cout<<"rssi"<<start_sniffer.rssi<<endl;
    cout<<"band[0]"<<start_sniffer.band[0]<<endl;
    cout<<"freq[0]"<<start_sniffer.freq[0]<<endl;
    cout<<"pci[0]"<<start_sniffer.pci[0]<<endl;
    len = packMsg1Param(PARA_TYPE_EUTRAN_CONFIG_CELL, sizeof(START_SNIFFER), (U8 *)&start_sniffer, payload);
    return true;
}
#endif

/*
bool ModuleFep::set_test_message(vector<string> &params, char *payload, U16 &len)
{
	int i = 0;
	int len1 = 0;

	char code[4];
	U32 data[20] = {0};
	char data_value[8];
	//char cmddata[128];
	if(params.size() < 2)
	{	
		cout<<"TOO few arguments"<<endl;
		cout<<"usage:cmdcode <code> data <data>"<<endl;
		return false;
	}
cout<<params[i].c_str()<<endl;
	if(params[++i].compare("code") != 0 )
	{
		cout<<"command not support"<<endl;
		return false;
	}
	cout<<params[i].c_str()<<endl;
	if(params[++i].length() > 4)
	{
		cout<<"command not support"<<endl;
		return false;
	}
	len1 = params[++i].length();
	if (len1 %4 != 0)
	{
		cout<<"error data please input a gain";
		return false;
	}
	
//	strcpy(code, params[i].c_str());
#if 0
	if (params[++i].length() > 128)
	{
		cout<<"command not support"<<endl;
		return false;
	}
	//strcpy(cmddata, params[i].c_str());
#endif
	
	cout<<params[i].c_str()<<endl;
	cout<<params[i].length()<<endl;
    len = packMsg2Param( PARA_TYPE_TEST_CMDCODE, params[i].length(), (U8 *)params[i].c_str(), PARA_TYPE_TEST_CMDDATA, params[i].length(), (U8 *)params[i].c_str(),  payload);
	return true;
}*/

ModuleWcdma::ModuleWcdma():Module(MODULE_WCDMA_CAP, "wcdma")
{
    createCmd(MODULE_WCDMA_CAP, CMD_SET, CMD_WCDMA_RESTART, "restart", "Restart wcdma module.");    
    createCmd(MODULE_WCDMA_CAP, CMD_SET, CMD_WCDMA_WIRELESS_OFF, "stop", "Usage: stop.");    
    createCmd(MODULE_WCDMA_CAP, CMD_SET, CMD_WCDMA_WIRELESS_ON, "start", "Usage: start.");    
    createCmd(MODULE_WCDMA_CAP, CMD_GET, CMD_WCDMA_GET_MODULE_STATUS, "status", "Get wcdma module status.");
    createCmd(MODULE_WCDMA_CAP, CMD_GET, CMD_WCDMA_GET_MODULE_CFG, "displaycfg", "Usage: displaycfg.");
    createCmd(MODULE_WCDMA_CAP, CMD_SET, CMD_WCDMA_CFG_WIRELESS, "config", "Usage: config [nodeb <mcc><mnc><lac><arfcn><psc><rac><cellid>]|[autolac <autolac>]|[dac <dac> txpower <txPower>]"); 
    createCmd(MODULE_WCDMA_CAP, CMD_GET, CMD_WCDMA_GET_SEND_COUNTER,  "getcounter", "get internal sending counter.");
    createCmd(MODULE_WCDMA_CAP, CMD_SET, CMD_WCDMA_TX_ATTUATION,  "settxatt", "Usage: settxatt <attuation (0~90 dB)>.");
}

bool ModuleWcdma::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool result = false;

    len = 0;
    switch(cmdCode)
    {
        case CMD_WCDMA_RESTART:
        case CMD_WCDMA_WIRELESS_OFF:
        case CMD_WCDMA_WIRELESS_ON:
        case CMD_WCDMA_GET_MODULE_STATUS:
        case CMD_WCDMA_GET_SEND_COUNTER:
		case CMD_WCDMA_GET_MODULE_CFG:	
            result = true;
            break;
        case CMD_WCDMA_CFG_WIRELESS:
            result = buildCfgWcdmaCapModule(params, payload, len);
            break;
        case CMD_WCDMA_TX_ATTUATION:
            result = buildSetWcdmaTxAttuation(params, payload, len);
            break;
        default:
            cout << __func__ << "  Unknown cmdCode: " << cmdCode << endl;              
            break;
    }

    return result;
}

bool ModuleWcdma::buildSetWcdmaTxAttuation(vector<string> &params, char *payload, U16 &len)
{
    int attuation = 0;

    if (params.size() < 2)
    {
        cout << "Parameter number should be 2" << endl;
        return false;
    }

    attuation = atoi(params[1].c_str());

    if(attuation > 90 || attuation <= 0)
    {
        cout << "attuation should be larger than 0, and smaller or equal than 90" << endl;
        return false;
    }

    len = packMsg1Param(PARA_TYPE_TX_ATTUATION, 4,  (U8 *)&attuation , payload);

    return true;
}

bool ModuleWcdma::buildCfgWcdmaCapModule(vector<string> &params, char *payload, U16 &len)
{
    U32 i = 1;
    wcdmaParam_t wcdma;

    if(params[i].compare("dac"))
	{
	    i++;
	    int dac = atoi(params[i].c_str());
    	len = packMsg1Param(PARA_TYPE_WCDMA_WIRELESS_CONFIG_DAC, sizeof(wcdmaParam_t),  (U8 *)&dac , payload);	
    }
    if(params[i].compare("autolac"))
	{
	    i++;
	    int autolac = atoi(params[i].c_str());
    	len = packMsg1Param(PARA_TYPE_WCDMA_WIRELESS_CONFIG_AUTOLAC, sizeof(wcdmaParam_t),  (U8 *)&autolac , payload);		
    }
    if(params[i].compare("txpower"))
	{
	    i++;
	    int txPower = atoi(params[i].c_str());
    	len = packMsg1Param(PARA_TYPE_WCDMA_WIRELESS_CONFIG_TXPOWER, sizeof(wcdmaParam_t),  (U8 *)&txPower , payload);		
    }	
    if(params[i].compare("pilot"))
	{
	    i++;
	    int pilot = atoi(params[i].c_str());
    	len = packMsg1Param(PARA_TYPE_WCDMA_WIRELESS_CONFIG_PILOT, sizeof(wcdmaParam_t),  (U8 *)&pilot , payload);		
    }
    else if(params[i].compare("nodeb"))
	{
	    i++;
		
		if (params.size() < 8 && params.size() > 3)
		{
			cout << "parameters number should be 11 for total config" << endl;
			cout << "Usage: cfggsm nodeb [<mcc> <mnc> <lac> <arfcn> <psc> <rac> <cellid>]";
			cout << " "<< endl;
			return false;
		}
	
        wcdma.mcc = atoi(params[i++].c_str());
    	wcdma.mnc = atoi(params[i++].c_str());
    	wcdma.lac =  atoi(params[i++].c_str());
    	wcdma.arfcn = atoi(params[i++].c_str());
    	wcdma.psc = atoi(params[i++].c_str());
    	wcdma.rac = atoi(params[i++].c_str());
    	wcdma.autolac = atoi(params[i++].c_str());
    	wcdma.dac = atoi(params[i++].c_str());
    	wcdma.txPower = atoi(params[i++].c_str()); 
    	wcdma.rxPower  = atoi(params[i++].c_str()); 

     	cout << " configuration:" << endl; 
    	cout << "    mcc: " << wcdma.mcc << endl;
    	cout << "    mnc: " << wcdma.mnc << endl;
    	cout << "    lac: " << wcdma.lac << endl;
    	cout << "    arfcn: " << wcdma.arfcn << endl;
    	cout << "    psc: " << wcdma.psc << endl;    
    	cout << "    rac: " << wcdma.rac << endl;
    	cout << "    autolac: " << wcdma.autolac << endl;
    	cout << "    dac: " << wcdma.dac << endl;
    	cout << "    txpower: " << wcdma.txPower << endl;
    	cout << "    rxpower: " << wcdma.rxPower << endl;   	
    	len = packMsg1Param(PARA_TYPE_WCDMA_WIRELESS_CONFIG_NODEB, sizeof(wcdmaParam_t),  (U8 *)&wcdma , payload);    	
	}
	else
	{
	    cout << params[i] << ": command not supported" << endl;
	}

    return true;
}

bool ModuleWcdma::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;

    bool rc = false;

    switch(pCmd->cmdCode)
    {
        case CMD_WCDMA_RESTART:
        case CMD_WCDMA_WIRELESS_OFF:
        case CMD_WCDMA_WIRELESS_ON:
        case CMD_WCDMA_CFG_WIRELESS:    
        case CMD_WCDMA_CFG_AIR_SNIFFER:
        case CMD_WCDMA_TX_ATTUATION:
            rc = decodeGeneralCmdResponse(pCmd, out_r);
            break;            

        case CMD_WCDMA_GET_MODULE_STATUS:
            rc = decodeGetWcdmaModuleStatus(pCmd, out_r);
            break;

        case CMD_WCDMA_GET_MODULE_CFG:            
            rc = decodeGetWcdmaModuleConfiguration(pCmd, out_r);
            break;

        case CMD_WCDMA_GET_SEND_COUNTER:
            rc = decodeGetWcdmaSendingCounter(pCmd, out_r);
            break;
        default:
            oss << __func__ << " Unknown cmdCode:" << pCmd->cmdCode << endl;
            break;
    } 

    out_r += oss.str();
    return rc;
}

bool ModuleWcdma::decodeGetWcdmaModuleConfiguration(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    wcdmaParam_t * wcdma;
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_WCDMA_WIRELESS_CONFIGURATION:
                wcdma = (wcdmaParam_t *) paraValue;
				oss << " configuration:" << endl; 
				oss << "	 mcc: " << wcdma->mcc << endl;
				oss << "	 mnc: " << wcdma->mnc << endl;
				oss << "	 lac: " << wcdma->lac << endl;
				oss << "	 arfcn: " << wcdma->arfcn << endl;
				oss << "	 psc: " << wcdma->psc << endl;	 
				oss << "	 rac: " << wcdma->rac << endl;
				oss << "	 autolac: " << wcdma->autolac << endl;
				oss << "	 dac: " << wcdma->dac << endl;
				oss << "	 txpower: " << wcdma->txPower << endl;
				oss << "	 rxpower: " << wcdma->rxPower << endl;
                break;
            case PARA_TYPE_RESULT:
                oss << matchStringValue(operationResult, *((U32 *)paraValue)) << endl;
                break;
            case PARA_TYPE_ERROR_CODE:
                oss << ", failure cause: " << matchStringValue(errorInfo, *((U32 *)paraValue)) << endl; 
                break;                
            default:
                oss << __func__ << "  Unknown result type: " << paraType << endl;
                break;
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "  Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();    
    return true;
}

bool ModuleWcdma::decodeGetWcdmaModuleStatus(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_WCDMA_MODULE_STATUS:
                 oss << "WCDMA Module State: " << paraValue << endl;
                 break;
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;                 
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

bool ModuleWcdma::decodeGetWcdmaSendingCounter(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    U32 *value;
    U32 i = 0;
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_WCDMA_SEND_COUNTER:
                 value = (U32 *)paraValue;
                 oss << "RC_OK: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_FAIL: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_OUT_OF_MEMORY: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_NULL_RESULT: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_MSG_TOO_LONG: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_MSG_NO_BUFF: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_MSG_DST_INVALID: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_MSG_QUEUE_FULL: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_MSG_CORRUPTED: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_MSG_INVALID_VALUE: " << setw(20) << *(value + (i++)) << endl;
                 oss << "RC_UDP_COUNTER: " << setw(20) << *(value + (i++)) << endl;
                 break;
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;                 
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}

ModuleTdscdma::ModuleTdscdma():Module(MODULE_TDSCDMA_CAP, "tdscdma")
{
    createCmd(MODULE_TDSCDMA_CAP, CMD_SET, CMD_TDSCDMA_RESTART,   "restart", "Restart wcdma module.");    
    createCmd(MODULE_TDSCDMA_CAP, CMD_SET, CMD_TDSCDMA_WIRELESS_OFF,     "stop", "Usage: stop.");    
    createCmd(MODULE_TDSCDMA_CAP, CMD_SET, CMD_TDSCDMA_WIRELESS_ON,       "start", "Usage: start.");    
    createCmd(MODULE_TDSCDMA_CAP, CMD_GET, CMD_TDSCDMA_GET_MODULE_STATUS, "status", "Get tdscdma module status.");
    createCmd(MODULE_TDSCDMA_CAP, CMD_GET, CMD_TDSCDMA_GET_MODULE_CFG,    "displaycfg", "Usage: displaycfg.");
    createCmd(MODULE_TDSCDMA_CAP, CMD_GET, CMD_TDSCDMA_GET_MODULE_INFO,       "mscinfo", "Usage: mscinfo swverion | sync| rf.");    
    createCmd(MODULE_TDSCDMA_CAP, CMD_SET, CMD_TDSCDMA_CFG_WIRELESS,      "setArfcn", "Usage: setArfcn <arfcn>"); 
    createCmd(MODULE_TDSCDMA_CAP, CMD_SET, CMD_TDSCDMA_TX_ATTUATION,  "settxatt", "Usage: settxatt <attuation (0~90 dB)>.");
    createCmd(MODULE_TDSCDMA_CAP, CMD_SET, CMD_TDSCDMA_DO_SNIFFER,  "sniffer", "Usage: sniffer.");
    createCmd(MODULE_TDSCDMA_CAP, CMD_GET, CMD_TDSCDMA_GET_SNIFFER_RESULT,  "snifresult", "Usage: snifresult.");

}

bool ModuleTdscdma::encode(U16 cmdCode, vector<string> &params, char *payload, U16 &len)
{
    bool result = false;

    len = 0;
    switch(cmdCode)
    {
        case CMD_TDSCDMA_RESTART:
        case CMD_TDSCDMA_WIRELESS_OFF:
        case CMD_TDSCDMA_WIRELESS_ON:
        case CMD_TDSCDMA_GET_MODULE_STATUS:
		case CMD_TDSCDMA_GET_MODULE_CFG:	
		case CMD_TDSCDMA_DO_SNIFFER:
		case CMD_TDSCDMA_GET_SNIFFER_RESULT:	
            result = true;
            break;
        case CMD_TDSCDMA_CFG_WIRELESS:
            result = buildCfgTdscdmaCapModule(params, payload, len);
            break;
        case CMD_TDSCDMA_TX_ATTUATION:
            result = buildSetTdscdmaTxAttuation(params, payload, len);
            break;
		case CMD_TDSCDMA_GET_MODULE_INFO:
			result = buildGetTdscdmaModuleInfo(params, payload, len);
			break;
        default:
            cout << __func__ << "  Unknown cmdCode: " << cmdCode << endl;              
            break;
    }

    return result;
}

bool ModuleTdscdma::buildGetTdscdmaModuleInfo(vector<string> &params, char *payload, U16 &len)
{
    uint32_t  i = 1;
	int32_t   paramType; 

    if(params[i].compare("swverion"))
	{
	   paramType =  PARA_TYPE_TDSCDMA_SOFTWARE_VERSION;
    }
	else if(params[i].compare("sync"))
	{
		paramType =  PARA_TYPE_TDSCDMA_SYNC_STATUS;
	}
	else if(params[i].compare("rf"))
	{
		paramType =  PARA_TYPE_TDSCDMA_WILELESS_STATE;
	}
	else
	{
	    cout << params[i] << ":command not support." << endl;
		return false;
	}

	//not parameter value needed
	len = packMsg1Param(paramType, sizeof(U32), (U8 *)&i , payload);

	return true;
}

bool ModuleTdscdma::buildSetTdscdmaTxAttuation(vector<string> &params, char *payload, U16 &len)
{
    int attuation = 0;

    if (params.size() < 2)
    {
        cout << "Parameter number should be 2" << endl;
        return false;
    }

    attuation = atoi(params[1].c_str());

    if(attuation > 90 || attuation <= 0)
    {
        cout << "attuation should be larger than 0, and smaller or equal than 90" << endl;
        return false;
    }

    len = packMsg1Param(PARA_TYPE_TX_ATTUATION, 4,  (U8 *)&attuation , payload);

    return true;
}

bool ModuleTdscdma::buildCfgTdscdmaCapModule(vector<string> &params, char *payload, U16 &len)
{
    int attuation = 0;

    if (params.size() < 2)
    {
        cout << "Parameter number should be 2" << endl;
        return false;
    }

    attuation = atoi(params[1].c_str());
    cout << "arfcn" << attuation << endl;
    len = packMsg1Param(PARA_TYPE_TDSCDMA_WIRELESS_CONFIG_ARFCN, 4,  (U8 *)&attuation , payload);

    return true;
}

bool ModuleTdscdma::decode(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;

    bool rc = false;

    switch(pCmd->cmdCode)
    {
		case CMD_TDSCDMA_RESTART:
		case CMD_TDSCDMA_WIRELESS_OFF:
		case CMD_TDSCDMA_WIRELESS_ON:
        case CMD_TDSCDMA_CFG_WIRELESS:
        case CMD_TDSCDMA_TX_ATTUATION:
		case CMD_TDSCDMA_DO_SNIFFER:			
            rc = decodeGeneralCmdResponse(pCmd, out_r);
            break;            
        case CMD_TDSCDMA_GET_MODULE_STATUS:
            rc = decodeGetTscdmaModuleStatus(pCmd, out_r);
            break;
        case CMD_TDSCDMA_GET_MODULE_CFG:            
            rc = decodeGetTscdmaModuleConfiguration(pCmd, out_r);
            break;
        case CMD_TDSCDMA_GET_SNIFFER_RESULT:
            rc = decodeGetTdscdmaSnifferResult(pCmd, out_r);
            break;
		case CMD_TDSCDMA_GET_MODULE_INFO:
            rc = decodeGetTdscdmaModuleInfo(pCmd, out_r);
            break;			
        default:
            oss << __func__ << " Unknown cmdCode:" << pCmd->cmdCode << endl;
            break;
    } 

    out_r += oss.str();
    return rc;
}

bool ModuleTdscdma::decodeGetTdscdmaModuleInfo(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_TDSCDMA_WILELESS_STATE:
                 //oss << "TDSCDMA radio status: " << (*paraValue == 0) ? "OFF": "ON" << endl;
                 break;
            case PARA_TYPE_TDSCDMA_SOFTWARE_VERSION:
                 oss << "TDSCDMA hw Version: " << paraValue << endl;
                 break;
            case PARA_TYPE_TDSCDMA_SYNC_STATUS:
                 oss << "TDSCDMA Sync State: " << paraValue << endl;
                 break;				 
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;                 
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;

}

bool ModuleTdscdma::decodeGetTdscdmaSnifferResult(PCMDHEADER pCmd, string & out_r)
{

    return true;
}
bool ModuleTdscdma::decodeGetTscdmaModuleConfiguration(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    tdscdmaParam_t * tdscdma;
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_TDSCDMA_WIRELESS_CONFIGURATION:
                tdscdma = (tdscdmaParam_t *) paraValue;
				oss << " configuration:" << endl; 
				oss << "	 mcc: " << tdscdma->mcc << endl;
				oss << "	 mnc: " << tdscdma->mnc << endl;
				oss << "	 lac: " << tdscdma->lac << endl;
				oss << "	 arfcn: " << tdscdma->arfcn << endl;
				oss << "	 psc: " << tdscdma->psc << endl;	 
				oss << "	 rac: " << tdscdma->rac << endl;
				oss << "	 autolac: " << tdscdma->autolac << endl;
				oss << "	 dac: " << tdscdma->dac << endl;
				oss << "	 txpower: " << tdscdma->txPower << endl;
				oss << "	 rxpower: " << tdscdma->rxPower << endl;
                break;
            case PARA_TYPE_RESULT:
                oss << matchStringValue(operationResult, *((U32 *)paraValue)) << endl;
                break;
            case PARA_TYPE_ERROR_CODE:
                 oss << ", failure cause: " << matchStringValue(errorInfo, *((U32 *)paraValue)) << endl; 
                 break;                
            default:
                oss << __func__ << "  Unknown result type: " << paraType << endl;
                break;
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "  Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();    
    return true;
}

bool ModuleTdscdma::decodeGetTscdmaModuleStatus(PCMDHEADER pCmd, string & out_r)
{
    ostringstream oss;
    PPARAM pParam =(PPARAM)(pCmd+1);
    U32 len = pCmd->cmdLength;
    U32 paraType;
    U32 paraLength;
    U8* paraValue;
    UNPACK_RESULT uprc; 
    
    while((uprc=CM_paraUnpackPara(&pParam, &len, &paraType, &paraLength,&paraValue)) == UNPACK_OK)
    {
        switch(paraType)
        {
            case PARA_TYPE_TDSCDMA_MODULE_STATUS:
                 oss << "TDSCDMA Module State: " << paraValue << endl;
                 break;
            default:
                oss << __func__ << "Unknown result type: " << paraType << endl;
                break;                 
        }
    }

    if( uprc == UNPACK_ERROR )
    {
        oss << __func__  << "Parameter error in received cmdcode " << pCmd->cmdCode << endl;
        out_r += oss.str();

        return false;
    }

    out_r += oss.str();
    return true;
}


